diff --git a/sdk/base.hpp b/sdk/base.hpp index 67aad14..649d005 100644 --- a/sdk/base.hpp +++ b/sdk/base.hpp @@ -34,7 +34,6 @@ #include #include #include -#include #include #include diff --git a/sdk/base/basic/huffman_coding.cpp b/sdk/base/basic/huffman_coding.cpp index d85e495..fbddd84 100644 --- a/sdk/base/basic/huffman_coding.cpp +++ b/sdk/base/basic/huffman_coding.cpp @@ -43,6 +43,9 @@ huffman_coding &huffman_coding::learn() { _codetable.clear(); _reverse_codetable.clear(); + // _measure .. count(weight) by symbol, see hc_t::operator + // _btree .. merge by weight until (1 == size()), see hc_comparator::operator + _measure.for_each([&](hc_t const &t) -> void { _btree.insert(t); }); while (_btree.size() > 1) { @@ -62,7 +65,7 @@ huffman_coding &huffman_coding::learn() { k.weight = k_lhs.weight + k_rhs.weight; k.flags = 1; // merged - typename btree_t::node_t *newone = _btree.insert(k, _btree._root); // merged + typename btree_t::node_t *newone = _btree.add(k); // merged map_pib_t pib = _m.insert(std::make_pair(k, _btree.clone_nocascade(newone))); pib.first->second->_left = l; @@ -77,9 +80,10 @@ huffman_coding &huffman_coding::infer() { if (root) { hc_temp hc; + // generate code .. left '0', right '1' infer(hc, root); - clear(root); + _btree.clean(root); } return *this; @@ -377,8 +381,6 @@ huffman_coding::node_t *huffman_coding::build(node_t **root) { return p; } -void huffman_coding::clear(node_t *&root) { _btree.clear(root); } - void huffman_coding::build(typename btree_t::node_t *&p) { if (p) { if (p->_left) { @@ -391,7 +393,7 @@ void huffman_coding::build(typename btree_t::node_t *&p) { if (_m.end() != iter) { typename btree_t::node_t *t = iter->second; - _btree.clear(p); + _btree.clean(p); p = t; _m.erase(iter); } diff --git a/sdk/base/basic/huffman_coding.hpp b/sdk/base/basic/huffman_coding.hpp index 52f6bb0..120848f 100644 --- a/sdk/base/basic/huffman_coding.hpp +++ b/sdk/base/basic/huffman_coding.hpp @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include @@ -120,6 +120,7 @@ class huffman_coding { * { 1, "11111111111111111011000" }, * { 2, "1111111111111111111111100010" }, * // ... + * { 0, nullptr }, * }; * * huffman_coding huff; @@ -133,6 +134,7 @@ class huffman_coding { * { 1, "11111111111111111011000" }, * { 2, "1111111111111111111111100010" }, * // ... + * { 0, nullptr }, * }; * * huffman_coding huff; @@ -183,7 +185,6 @@ class huffman_coding { protected: node_t *build(node_t **root = nullptr); - void clear(node_t *&root); void build(typename btree_t::node_t *&p); void infer(hc_temp &hc, typename btree_t::node_t *t); diff --git a/sdk/base/basic/keyvalue.hpp b/sdk/base/basic/keyvalue.hpp index 70671d8..ddccd4d 100644 --- a/sdk/base/basic/keyvalue.hpp +++ b/sdk/base/basic/keyvalue.hpp @@ -70,7 +70,7 @@ class t_skey_value { } /** - * @brief add, kv_update + * @brief add, update * @param const std::string& name [IN] * @param const value_t& value [IN] * @param uint32 mode [INOPT] see key_value_mode_t @@ -110,14 +110,14 @@ class t_skey_value { return ret; } /** - * @brief kv_update + * @brief update * @param const std::string& name [in] * @param const value_t& value [in] * @return error code (see error.hpp) * @remarks * set(name, value, key_value_mode_t::kv_update); */ - return_t kv_update(const std::string& name, const value_t& value) { return set(name, value, key_value_mode_t::kv_update); } + return_t update(const std::string& name, const value_t& value) { return set(name, value, key_value_mode_t::kv_update); } /** * @brief remove * @param const std::string& name [IN] @@ -170,7 +170,7 @@ class t_skey_value { /** * @brief exist * @remarks - * kv.kv_update ("key", "value"); + * kv.update ("key", "value"); * result = exist ("key"); // true * result = exist ("value"); // false */ @@ -198,7 +198,7 @@ class t_skey_value { * @brief return value by key * @param const std::string& name * @remarks - * kv.kv_update ("key", "value"); + * kv.update ("key", "value"); * value = kv ["key"]; // "value" * value = kv ["value"]; // nullptr */ @@ -228,7 +228,7 @@ class t_skey_value { * @param value_t& value [OUT] * @return error code (see error.hpp) * @remarks - * kv.kv_update ("key", "value"); + * kv.update ("key", "value"); * kv.query ("key", value); // "value" * kv.query ("value", value); // "" */ diff --git a/sdk/base/basic/nostd/container.hpp b/sdk/base/basic/nostd/container.hpp index 5a24f72..03b6779 100644 --- a/sdk/base/basic/nostd/container.hpp +++ b/sdk/base/basic/nostd/container.hpp @@ -12,19 +12,33 @@ #ifndef __HOTPLACE_SDK_BASE_BASIC_NOSTD_CONTAINER__ #define __HOTPLACE_SDK_BASE_BASIC_NOSTD_CONTAINER__ -#include -#include -#include #include #include -#include +//#include #include #include namespace hotplace { +/** + * @remarks + * where 0 seek_begin, 1 seek_set, 2 seek_end + */ + +template +void for_each_const(const container_t& c, typename std::function f) { + if (c.size()) { + auto iter = c.begin(); + f(iter++, 0); + while (c.end() != iter) { + f(iter++, 1); + } + f(c.end(), 2); + } +} + template -void for_each(const container_t& c, typename std::function f) { +void for_each(container_t& c, typename std::function f) { if (c.size()) { auto iter = c.begin(); f(iter++, 0); @@ -36,20 +50,22 @@ void for_each(const container_t& c, typename std::function -void print(const container_t& c, stream_type& s) { - for_each(c, [&](typename container_t::const_iterator iter, int where) -> void { +void print(const container_t& c, stream_type& s, const std::string& mark_prologue = "[", const std::string& mark_delimiter = ", ", + const std::string& mark_epilogue = "]") { + auto func = [&](typename container_t::const_iterator iter, int where) -> void { switch (where) { case 0: - s << "[" << *iter; + s << mark_prologue << *iter; break; case 1: - s << ", " << *iter; + s << mark_delimiter << *iter; break; case 2: - s << "]"; + s << mark_epilogue; break; } - }); + }; + for_each_const(c, func); } } // namespace hotplace diff --git a/sdk/base/basic/nostd/exception.hpp b/sdk/base/basic/nostd/exception.hpp new file mode 100644 index 0000000..6722d1a --- /dev/null +++ b/sdk/base/basic/nostd/exception.hpp @@ -0,0 +1,44 @@ +/* vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab smarttab : */ +/** + * @file {file} + * @author Soo Han, Kim (princeb612.kr@gmail.com) + * @desc + * + * Revision History + * Date Name Description + * + */ + +#ifndef __HOTPLACE_SDK_BASE_BASIC_EXCEPTION__ +#define __HOTPLACE_SDK_BASE_BASIC_EXCEPTION__ + +#include +#include +#include +#include + +namespace hotplace { + +class exception { + private: + errorcode_t _errorcode; + std::string _desc; + + public: + exception(errorcode_t err) { _errorcode = err; } + exception(errorcode_t err, const std::string& desc) : _errorcode(err), _desc(desc) {} + exception(const exception& rhs) : _errorcode(rhs._errorcode), _desc(rhs._desc) {} + exception(exception&& rhs) : _errorcode(rhs._errorcode), _desc(std::move(rhs._desc)) {} + + errorcode_t get_errorcode() const { return _errorcode; } + std::string get_error_message() const { + std::string msg; + error_advisor::get_instance()->error_message(_errorcode, msg); + return msg; + } + std::string get_description() const { return _desc; } +}; + +} // namespace hotplace + +#endif diff --git a/sdk/base/basic/nostd/graph.hpp b/sdk/base/basic/nostd/graph.hpp new file mode 100644 index 0000000..fedb117 --- /dev/null +++ b/sdk/base/basic/nostd/graph.hpp @@ -0,0 +1,479 @@ +/* vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab smarttab : */ +/** + * @file {file} + * @author Soo Han, Kim (princeb612.kr@gmail.com) + * @desc + * + * Revision History + * Date Name Description + * + * graph online https://graphonline.ru/en/ + */ + +#ifndef __HOTPLACE_SDK_BASE_BASIC_NOSTD_GRAPH__ +#define __HOTPLACE_SDK_BASE_BASIC_NOSTD_GRAPH__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace hotplace { + +/** + * sketch + * + * t_graph graph; + * graph.add_edge(1, 2) + * .add_edge(1, 3) + * .add_edge(1, 4) + * .add_edge(2, 4) + * .add_edge(2, 5) + * .add_edge(3, 6) + * .add_edge(4, 3) + * .add_edge(4, 6) + * .add_edge(4, 7) + * .add_edge(5, 4) + * .add_edge(5, 7) + * .add_edge(7, 6); + * // set weight and direction + * // g.add_edge(1, 8, 1, graph_direction_t::graph_undirected); + * // g.add_edge(7, 8, 2, graph_direction_t::graph_undirected); + * auto dfs = graph.build_dfs() + * dfs->learn().infer(); + * auto infer_handler = [](const int& i, const std::vector& v) -> void { + * basic_stream bs; + * print, basic_stream>(v, bs, "(", ", ", ")"); + * std::cout << bs << std::endl; + * fflush(stdout); + * }; + * dfs->traverse(handler); + */ +enum graph_direction_t { + graph_undirected = 0, + graph_directed = 1, +}; + +template +class t_graph { + private: + enum label_t { + label_unvisited = 0, + label_visited = 1, + }; + + struct vertex { + T _data; + + vertex(const T& d = T()) : _data(d) {} + vertex(T&& d) : _data(std::move(d)) {} + + vertex(const vertex& rhs) : _data(rhs._data) {} + vertex(vertex&& rhs) : _data(std::move(rhs._data)) {} + }; + struct edge { + vertex _from; + vertex _to; + int _weight; + graph_direction_t _direction; + + edge(const T& from, const T& to, int weight = 0, graph_direction_t d = graph_directed) : _from(from), _to(to), _direction(d), _weight(weight) {} + edge(T&& from, T&& to, int weight = 0, graph_direction_t d = graph_directed) + : _from(std::move(from)), _to(std::move(to)), _weight(weight), _direction(d) {} + + edge(const vertex& from, const vertex& to, int weight = 0, graph_direction_t d = graph_directed) + : _from(from), _to(to), _weight(weight), _direction(d) {} + edge(vertex&& from, vertex&& to, graph_direction_t d = graph_directed, int weight = 0) + : _from(std::move(from)), _to(std::move(to)), _weight(weight), _direction(d) {} + + edge(const edge& rhs) : _from(rhs._from), _to(rhs._to), _weight(rhs._weight), _direction(rhs._direction) {} + edge(edge&& rhs) : _from(std::move(rhs._from)), _to(std::move(rhs._to)), _weight(rhs._weight), _direction(rhs._direction) {} + + void set_weight(int weight) { _weight = weight; } + int get_weight() { return _weight; } + void set_direction(graph_direction_t d) { _direction = d; } + graph_direction_t get_direction() { return _direction; } + }; + /** + * @brief tag + * @comments + * weight, direction - unchangable + * label, distance - changable + */ + struct tag { + label_t _label; + int _distance; + + tag() : _label(label_unvisited), _distance(-1) {} + tag(const tag& rhs) : _label(rhs._label), _distance(rhs._distance) {} + + void set_label(label_t tag) { _label = tag; } + label_t get_label() { return _label; } + + void unvisit() { set_label(label_unvisited); } + void visit() { set_label(label_visited); } + + bool is_unvisited() { return label_unvisited == get_label(); } + bool is_visited() { return label_visited == get_label(); } + + void set_distance(int distance) { _distance = distance; } + int get_distance() { return _distance; } + }; + + friend bool operator<(const vertex& lhs, const vertex& rhs) { return lhs._data < rhs._data; } + friend bool operator==(const vertex& lhs, const vertex& rhs) { return lhs._data == rhs._data; } + friend bool operator<(const edge& lhs, const edge& rhs) { + bool ret = true; + if (lhs._from < rhs._from) { + // do nothing + } else if (lhs._from == rhs._from) { + ret = (lhs._to < rhs._to); + } else { + ret = false; + } + return ret; + } + + typedef std::set unordered_vertices_t; + typedef std::set unordered_edges_t; + typedef std::list ordered_vertices_t; + typedef std::list ordered_edges_t; + typedef std::map adjacent_t; + typedef std::map vertices_tags_t; + + public: + t_graph() {} + + t_graph& add_vertex(const T& d) { + vertex v(d); + add_vertex(std::move(v)); + return *this; + } + t_graph& add_vertex(T&& d) { + add_vertex(vertex(std::move(d))); + return *this; + } + t_graph& add_vertex(const vertex& v) { + std::pair pib = _unordered_vertices.insert(v); + if (true == pib.second) { + _ordered_vertices.push_back(v); + } + return *this; + } + t_graph& add_vertex(vertex&& v) { + std::pair pib = _unordered_vertices.insert(std::move(v)); + if (true == pib.second) { + _ordered_vertices.push_back(v); + } + return *this; + } + + t_graph& add_edge(const T& from, const T& to, int weight = 0, graph_direction_t d = graph_directed) { + edge e(from, to, weight, d); + add_edge(std::move(e)); + return *this; + } + t_graph& add_edge(const vertex& from, const vertex& to, int weight = 0, graph_direction_t d = graph_directed) { + edge e(from, to, weight, d); + add_edge(std::move(e)); + return *this; + } + + t_graph& add_directed_edge(const T& from, const T& to, int weight = 0) { return add_edge(from, to, weight, graph_direction_t::graph_directed); } + t_graph& add_directed_edge(const vertex& from, const vertex& to, int weight = 0) { return add_edge(from, to, weight, graph_direction_t::graph_directed); } + t_graph& add_undirected_edge(const T& from, const T& to, int weight = 0) { return add_edge(from, to, weight, graph_direction_t::graph_undirected); } + t_graph& add_undirected_edge(const vertex& from, const vertex& to, int weight = 0) { + return add_edge(from, to, weight, graph_direction_t::graph_undirected); + } + + t_graph& add_edge(const edge& e) { + std::pair pib = _unordered_edges.insert(e); + if (pib.second) { + add_vertex(e._from).add_vertex(e._to); + + _ordered_edges.push_back(e); + } + + return *this; + } + t_graph& add_edge(edge&& e) { + edge temp(std::move(e)); + return add_edge(temp); + } + + const unordered_vertices_t& get_unordered_vertices() const { return _unordered_vertices; } + const unordered_edges_t& get_unordered_edges() const { return _unordered_edges; } + const ordered_vertices_t& get_ordered_vertices() const { return _ordered_vertices; } + const ordered_edges_t& get_ordered_edges() const { return _ordered_edges; } + + private: + unordered_vertices_t _unordered_vertices; + unordered_edges_t _unordered_edges; + ordered_vertices_t _ordered_vertices; + ordered_edges_t _ordered_edges; + + public: + class graph_search { + public: + typedef std::vector result_t; + typedef std::map results_map_t; + typedef std::function&)> visitor_t; + + graph_search(const t_graph& g) : _g(g) {} + + virtual graph_search& learn() { + build_tags(); + build_adjacent_list(_adjacent); + + do_learn(); + return *this; + } + + virtual graph_search& infer() { + _results.clear(); + for (auto v : _vertices_tags) { + do_infer(v.first._data); + } + return *this; + } + virtual graph_search& infer(const T& u) { + _results.clear(); + do_infer(u); + return *this; + } + + virtual void traverse(visitor_t f) { + for (auto v : _vertices_tags) { + do_traverse(v.first._data, f); + } + } + virtual void traverse(const T& u, visitor_t f) { do_traverse(u, f); } + + bool touch_tag(std::function f) { + for (auto& item : _vertices_tags) { + f(item.second); + } + return true; + } + bool touch_tag(const vertex& u, std::function f) { + bool ret = false; + typename vertices_tags_t::iterator iter = _vertices_tags.find(u); + if (_vertices_tags.end() != iter) { + ret = f(iter->second); + } + return ret; + } + + protected: + virtual void do_learn() {} + virtual void do_infer(const T& u) {} + virtual void do_traverse(const T& u, visitor_t f) { f(u, _results[u]); } + + graph_search& build_tags() { + for (auto v : _g._ordered_vertices) { + _vertices_tags.insert(std::make_pair(v, tag())); + } + return *this; + } + + void build_adjacent_list(adjacent_t& target) { + target.clear(); + for (auto v : _g._ordered_vertices) { + ordered_vertices_t ovl; + target.insert(std::make_pair(v, std::move(ovl))); + } + for (auto e : _g._ordered_edges) { + target.find(e._from)->second.push_back(e._to); + if (graph_undirected == e.get_direction()) { + target.find(e._to)->second.push_back(e._from); + } + } + } + + void reset_visit() { + auto handler = [](tag& t) -> bool { + t.unvisit(); + return true; + }; + touch_tag(handler); + } + + bool mark_visited(const T& v) { return mark_visited(vertex(v)); } + + bool mark_visited(const vertex& v) { + auto handler = [](tag& t) -> bool { + bool ret = false; + if (t.is_unvisited()) { + t.visit(); + ret = true; + } + return ret; + }; + return touch_tag(v, handler); + }; + + const t_graph& _g; + vertices_tags_t _vertices_tags; // visited, unvisited + adjacent_t _adjacent; + results_map_t _results; + }; + + class graph_adjacent_list : public graph_search { + public: + typedef typename graph_search::visitor_t visitor_t; + + graph_adjacent_list(const t_graph& g) : graph_search(g) {} + + protected: + virtual void do_infer(const T& u) { + auto it = this->_adjacent.find(u); + if (this->_adjacent.end() != it) { + auto& result = this->_results[u]; + result.insert(result.end(), u); + for (auto lit : it->second) { + result.insert(result.end(), lit._data); + } + } + } + + private: + }; + + /* + * @brief depth first search + * @refer + * DFS(G, u) + * u.visited = true + * for each v ∈ G.Adj[u] + * if v.visited == false + * DFS(G,v) + * + * init() { + * For each u ∈ G + * u.visited = false + * For each u ∈ G + * DFS(G, u) + * } + */ + class graph_dfs : public graph_search { + public: + typedef typename graph_search::result_t result_t; + typedef typename graph_search::visitor_t visitor_t; + + graph_dfs(const t_graph& g) : graph_search(g) {} + + protected: + virtual void do_infer(const T& u) { + this->reset_visit(); + result_t& result = this->_results[u]; + result.insert(result.end(), u); + infer_recursive(u, result); + } + void infer_recursive(const T& u, result_t& result) { + this->mark_visited(u); + + auto& l = this->_adjacent.find(u)->second; + for (auto opposite : l) { + if (this->mark_visited(opposite)) { + const T& o = opposite._data; + result.insert(result.end(), o); + infer_recursive(o, result); + } + } + } + + private: + }; + + /* + * @brief breadth first search + * @refer + * create a queue Q + * mark v as visited and put v into Q + * while Q is non-empty + * remove the head u of Q + * mark and enqueue all (unvisited) neighbours of u + */ + class graph_bfs : public graph_search { + public: + typedef typename graph_search::visitor_t visitor_t; + + graph_bfs(const t_graph& g) : graph_search(g) {} + + protected: + virtual void do_infer(const T& u) { + this->reset_visit(); + std::list _queue; + _queue.push_front(u); + + this->mark_visited(u); + auto& result = this->_results[u]; + result.insert(result.end(), u); + + while (_queue.size()) { + T v = _queue.front(); + _queue.pop_front(); // remove the head + + // mark and enqueue all (unvisited) neighbours + auto& l = this->_adjacent.find(v)->second; + for (auto opposite : l) { + if (this->mark_visited(opposite)) { + const T& o = opposite._data; + result.insert(result.end(), o); + _queue.push_back(o); + } + } + } + } + + private: + }; + + /* + * @brief Dijkstra + * dijkstra(G, S) + * for each vertex V in G + * distance[V] <- infinite + * previous[V] <- NULL + * If V != S, add V to Priority Queue Q + * distance[S] <- 0 + * + * while Q IS NOT EMPTY + * U <- Extract MIN from Q + * for each unvisited neighbour V of U + * tempDistance <- distance[U] + edge_weight(U, V) + * if tempDistance < distance[V] + * distance[V] <- tempDistance + * previous[V] <- U + * return distance[], previous[] + */ + class graph_dijkstra : public graph_search { + public: + typedef typename graph_search::visitor_t visitor_t; + + graph_dijkstra(const t_graph& g) : graph_search(g) {} + + protected: + virtual void do_infer(const T& u) { + this->reset_visit(); + // + } + + private: + }; + + graph_adjacent_list* build_adjacent() { return new graph_adjacent_list(*this); } + graph_dfs* build_dfs() { return new graph_dfs(*this); } + graph_bfs* build_bfs() { return new graph_bfs(*this); } + graph_dijkstra* build_dijkstra() { return new graph_dijkstra(*this); } +}; + +} // namespace hotplace + +#endif diff --git a/sdk/base/basic/nostd/list.hpp b/sdk/base/basic/nostd/list.hpp new file mode 100644 index 0000000..f34281a --- /dev/null +++ b/sdk/base/basic/nostd/list.hpp @@ -0,0 +1,244 @@ +/* vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab smarttab : */ +/** + * @file {file} + * @author Soo Han, Kim (princeb612.kr@gmail.com) + * @desc + * + * Revision History + * Date Name Description + * + */ + +#ifndef __HOTPLACE_SDK_BASE_BASIC_NOSTD_LIST__ +#define __HOTPLACE_SDK_BASE_BASIC_NOSTD_LIST__ + +#include +#include +#include +#include + +namespace hotplace { + +/** + * @brief list + * @refer Data Structures and Algorithm Analysis in C++ - 3 Lists, Stacks, and Queues + */ +template +class t_list { + private: + struct node { + T _data; + node* _prev; + node* _next; + + node(const T& d = T(), node* prev = nullptr, node* next = nullptr) : _data(d), _prev(prev), _next(next) {} + node(T&& d, node* prev = nullptr, node* next = nullptr) : _data(std::move(d)), _prev(prev), _next(next) {} + }; + + public: + class const_iterator { + public: + const_iterator(const t_list& l, node* p) : _list(&l), _current(p) {} + + const T& operator*() const { return retrieve(); } + const_iterator& operator++() { + _current = _current->_next; + return *this; + } + const_iterator operator++(int) { + const_iterator old = *this; + ++(*this); + return old; + } + const_iterator& operator--() { + _current = _current->_prev; + return *this; + } + const_iterator operator--(int) { + const_iterator old = *this; + --(*this); + return old; + } + bool operator==(const const_iterator& rhs) const { return _current == rhs._current; } + bool operator!=(const const_iterator& rhs) const { return (false == (*this == rhs)); } + + void isvalid() const { + if (nullptr == _list || nullptr == _current || _current == _list->_head) { + throw exception(errorcode_t::bad_data); + } + } + + protected: + const t_list* _list; + node* _current; + T& retrieve() const { return _current->_data; } + const_iterator(node* p) : _current(p) {} + friend class t_list; + }; + class iterator : public const_iterator { + public: + iterator(const t_list& l, node* p) : const_iterator(l, p) {} + + T& operator*() { return const_iterator::retrieve(); } + const T& operator*() const { return const_iterator::operator*(); } + + iterator& operator++() { + this->_current = this->_current->_next; + return *this; + } + iterator operator++(int) { + iterator old = *this; + ++(*this); + return old; + } + iterator& operator--() { + this->_current = this->_current->_prev; + return *this; + } + iterator operator--(int) { + iterator old = *this; + --(*this); + return old; + } + + protected: + iterator(node* p) : const_iterator{p} {} + friend class t_list; + }; + + T& front() { return *begin(); } + const T& front() const { return *begin(); } + T& back() { return *--end(); } + const T& back() const { return *--end(); } + void push_front(const T& x) { insert(begin(), x); } + void push_front(T&& x) { insert(begin(), std::move(x)); } + void push_back(const T& x) { insert(end(), x); } + void push_back(T&& x) { insert(end(), std::move(x)); } + void pop_front() { erase(begin()); } + void pop_back() { erase(--end()); } + + iterator insert(iterator iter, const T& x) { + iter.isvalid(); + if (iter._list != this) { + throw exception(errorcode_t::mismatch); + } + node* p = iter._current; + _size++; + return iterator(*this, p->_prev = p->_prev->_next = new node(x, p->_prev, p)); + } + iterator insert(iterator iter, T&& x) { + node* p = iter._current; + _size++; + return p->_prev = p->_prev->_next = new node(std::move(x), p->_prev, p); + } + iterator erase(iterator iter) { + node* p = iter._current; + iterator ret{p->_next}; + p->_prev->_next = p->_next; + p->_next->_prev = p->_prev; + delete p; + _size--; + return ret; + } + iterator erase(iterator from, iterator to) { + for (iterator iter = from; iter != to;) { + iter = erase(iter); + } + return to; + } + + public: + t_list() { init(); } + t_list(const t_list& rhs) { + init(); + for (auto& x : rhs) { + push_back(x); + } + } + t_list(t_list&& rhs) : _size(rhs._size), _head(rhs._head), _tail(rhs._tail) { rhs.init(); } + ~t_list() { + clear(); + delete _head; + delete _tail; + } + + t_list& operator=(const t_list& rhs) { + t_list temp = rhs; + std::swap(*this, temp); + return *this; + } + t_list& operator=(t_list&& rhs) { + clear(); + std::swap(_size, rhs._size); + std::swap(_head, rhs._head); + std::swap(_tail, rhs._tail); + return *this; + } + + iterator begin() { + iterator iter(*this, _head); + return ++iter; + } + const_iterator begin() const { + const_iterator iter(*this, _head); + return ++iter; + } + iterator end() { return iterator(*this, _tail); } + const_iterator end() const { return const_iterator(*this, _tail); } + + int size() const { return _size; } + bool empty() const { return 0 == size(); } + void clear() { + while (false == empty()) { + pop_front(); + } + } + + private: + size_t _size; + node* _head; + node* _tail; + + void init() { + _size = 0; + _head = new node; + _tail = new node; + _head->_next = _tail; + _tail->_prev = _head; + } +}; + +/* + * @brief simple util + */ +template +class t_single_linkable { + public: + t_single_linkable() : _head(nullptr), _last(nullptr) {} + + bool add(single_linked_node_t* item) { + bool ret = true; + if (item) { + item->set_next(nullptr); + if (nullptr == _head) { + _head = item; + } + if (_last) { + _last->set_next(item); + } + _last = item; + } else { + ret = false; + } + return ret; + } + single_linked_node_t* get_head() { return _head; } + + private: + single_linked_node_t* _head; + single_linked_node_t* _last; +}; + +} // namespace hotplace + +#endif diff --git a/sdk/base/basic/nostd/pq.hpp b/sdk/base/basic/nostd/pq.hpp new file mode 100644 index 0000000..47499d0 --- /dev/null +++ b/sdk/base/basic/nostd/pq.hpp @@ -0,0 +1,120 @@ +/* vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab smarttab : */ +/** + * @file {file} + * @author Soo Han, Kim (princeb612.kr@gmail.com) + * @desc + * + * Revision History + * Date Name Description + * + */ + +#ifndef __HOTPLACE_SDK_BASE_BASIC_NOSTD_PRIORITYQUEUE__ +#define __HOTPLACE_SDK_BASE_BASIC_NOSTD_PRIORITYQUEUE__ + +#include +#include +#include +#include + +namespace hotplace { + +/** + * @brief heap + * @refer Data Structures and Algorithm Analysis in C++ - 6 Priority Queues (Heaps) + */ +template +class t_binary_heap { + public: + explicit t_binary_heap() : _array(10), _size(0) {} + explicit t_binary_heap(const t_binary_heap& rhs) : _array(rhs._array), _size(rhs._size) {} + explicit t_binary_heap(const t_vector& rhs) : _array(rhs.size() + 10), _size(rhs.size()) { + for (size_t i = 0; i < rhs.size(); ++i) { + _array[i + 1] = rhs[i]; + } + build_heap(); + } + + bool empty() const { return 0 == _size; } + const T& top() const { + if (empty()) { + throw exception(errorcode_t::empty); + } + return _array[1]; + } + + void push(const T& x) { + if (_size == _array.size() - 1) { + _array.resize(_array.size() << 1); + } + + size_t hole = ++_size; + + T copy = x; + _array[0] = std::move(copy); + for (; x < _array[hole / 2]; hole /= 2) { + _array[hole] = std::move(_array[hole / 2]); + } + _array[hole] = std::move(_array[0]); + } + void push(T&& x) { + if (_size == _array.size() - 1) { + _array.resize(_array.size() << 1); + } + + size_t hole = ++_size; + + _array[0] = std::move(x); + for (; x < _array[hole / 2]; hole /= 2) { + _array[hole] = std::move(_array[hole / 2]); + } + _array[hole] = std::move(_array[0]); + } + void pop() { + if (empty()) { + throw exception(errorcode_t::empty); + } + _array[1] = std::move(_array[_size--]); + percolate_down(1); + } + void pop(T& x) { + if (empty()) { + throw exception(errorcode_t::empty); + } + x = std::move(_array[1]); + _array[1] = std::move(_array[_size--]); + percolate_down(1); + } + void clear() { _size = 0; } + size_t size() { return _size; } + + private: + t_vector _array; + size_t _size; + + void build_heap() { + for (size_t i = _size / 2; i > 0; --i) { + percolate_down(i); + } + } + void percolate_down(size_t hole) { + size_t child = 0; + T tmp = std::move(_array[hole]); + for (; hole * 2 <= _size; hole = child) { + child = hole << 1; + if ((child != _size) && (_array[child + 1] < _array[child])) { + ++child; + } + if (_array[child] < tmp) { + _array[hole] = std::move(_array[child]); + } else { + break; + } + } + _array[hole] = std::move(tmp); + } +}; + +} // namespace hotplace + +#endif diff --git a/sdk/base/basic/tree.hpp b/sdk/base/basic/nostd/tree.hpp similarity index 97% rename from sdk/base/basic/tree.hpp rename to sdk/base/basic/nostd/tree.hpp index d612f94..2d9c62c 100644 --- a/sdk/base/basic/tree.hpp +++ b/sdk/base/basic/nostd/tree.hpp @@ -9,8 +9,8 @@ * */ -#ifndef __HOTPLACE_SDK_BASE_BASIC_TREE__ -#define __HOTPLACE_SDK_BASE_BASIC_TREE__ +#ifndef __HOTPLACE_SDK_BASE_BASIC_NOSTD_TREE__ +#define __HOTPLACE_SDK_BASE_BASIC_NOSTD_TREE__ #include #include @@ -23,14 +23,14 @@ namespace hotplace { -class huffman_coding; +// class huffman_coding; /** * @brief t_btree * @refer Data Structures and Algorithm Analysis in C++ - 4.3 The Search Tree ADT - Binary Search Trees */ template > class t_btree { - friend class huffman_coding; + // friend class huffman_coding; private: struct bnode { @@ -41,9 +41,9 @@ class t_btree { bnode(const key_t &key, bnode *lt = nullptr, bnode *rt = nullptr) : _key(key), _left(lt), _right(rt) {} bnode(key_t &&key, bnode *lt = nullptr, bnode *rt = nullptr) : _key{std::move(key)}, _left(lt), _right(rt) {} }; - typedef bnode node_t; public: + typedef bnode node_t; typedef typename std::function const_visitor; typedef typename std::function visitor; @@ -183,7 +183,6 @@ class t_btree { } t = nullptr; } - // void printTree(node_t *t, ostream &out) const; void walk(node_t *t, const_visitor visit) { if (t) { // in-order traverse @@ -200,9 +199,13 @@ class t_btree { return item; } + public: // added + node_t *root() const { return _root; } node_t *first() const { return find_min(_root); } node_t *clone_nocascade(node_t *p) { return p ? new node_t(p->_key) : nullptr; } + node_t *add(const key_t &x, visitor visit = nullptr) { return insert(x, _root, visit); } + void clean(node_t *&t) { clear(t); } }; /** @@ -225,9 +228,9 @@ class t_avltree { avlnode(const key_t &key, avlnode *lt = nullptr, avlnode *rt = nullptr, int height = 0) : _key(key), _left(lt), _right(rt), _height(height) {} avlnode(key_t &&key, avlnode *lt = nullptr, avlnode *rt = nullptr, int height = 0) : _key{std::move(key)}, _left(lt), _right(rt), _height(height) {} }; - typedef avlnode node_t; public: + typedef avlnode node_t; typedef typename std::function const_visitor; typedef typename std::function visitor; @@ -372,7 +375,6 @@ class t_avltree { } t = nullptr; } - // void printTree(node_t *t, ostream &out) const; void walk(node_t *t, const_visitor visit) { if (t) { // in-order traverse @@ -439,6 +441,7 @@ class t_avltree { rotate_right(k3); } + public: // added node_t *first() const { return find_min(_root); } }; diff --git a/sdk/crypto/cose/cose_binary.cpp b/sdk/crypto/cose/cose_binary.cpp new file mode 100644 index 0000000..a0675a8 --- /dev/null +++ b/sdk/crypto/cose/cose_binary.cpp @@ -0,0 +1,68 @@ +/* vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab smarttab : */ +/** + * @file {file} + * @author Soo Han, Kim (princeb612.kr@gmail.com) + * @desc + * + * Revision History + * Date Name Description + * + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace hotplace { +using namespace io; +namespace crypto { + +cose_binary::cose_binary() {} + +cose_binary& cose_binary::set_b16(const char* value) { + _payload.set_b16(value); + return *this; +} + +cose_binary& cose_binary::set_b16(const std::string& value) { + _payload.set_b16(value); + return *this; +} + +cose_binary& cose_binary::set(const std::string& value) { + _payload.set(value); + return *this; +} + +cose_binary& cose_binary::set(const binary_t& value) { + _payload.set(value); + return *this; +} + +return_t cose_binary::set(cbor_data* object) { return _payload.parse_payload(object); } + +cose_data& cose_binary::data() { return _payload; } + +bool cose_binary::empty() { return _payload.empty_binary(); } + +size_t cose_binary::size() { return _payload.size_binary(); } + +void cose_binary::get(binary_t& bin) { _payload.get_binary(bin); } + +cose_binary& cose_binary::clear() { + _payload.clear(); + return *this; +} + +cbor_data* cose_binary::cbor() { + cbor_data* object = nullptr; + _payload.build_data(&object); + return object; +} + +} // namespace crypto +} // namespace hotplace diff --git a/sdk/crypto/cose/cose_composer.cpp b/sdk/crypto/cose/cose_composer.cpp index f72042e..1cefbd7 100644 --- a/sdk/crypto/cose/cose_composer.cpp +++ b/sdk/crypto/cose/cose_composer.cpp @@ -21,1613 +21,6 @@ namespace hotplace { using namespace io; namespace crypto { -#define TYPE_STATIC_KEY (TYPE_USER) -#define TYPE_COUNTER_SIG (vartype_t)(TYPE_USER + 1) - -cose_data::cose_key::cose_key() : _curve(0) {} - -void cose_data::cose_key::set(crypto_key* key, uint16 curve, const binary_t& x, const binary_t& y) { - _curve = curve; - _x = x; - _y = y; - _compressed = false; - - crypto_advisor* advisor = crypto_advisor::get_instance(); - const hint_curve_t* hint = advisor->hintof_curve((cose_ec_curve_t)curve); - crypto_keychain keychain; - binary_t d; - keychain.add_ec(key, nullptr, hint->nid, x, y, d); -} - -void cose_data::cose_key::set(crypto_key* key, uint16 curve, const binary_t& x, bool ysign) { - _curve = curve; - _x = x; - _y.clear(); - _ysign = ysign; - _compressed = true; - - crypto_advisor* advisor = crypto_advisor::get_instance(); - const hint_curve_t* hint = advisor->hintof_curve((cose_ec_curve_t)curve); - crypto_keychain keychain; - binary_t d; - keychain.add_ec(key, nullptr, hint->nid, x, ysign, d); -} - -void cose_data::cose_key::set(cose_orderlist_t& order) { _order = order; } - -cbor_map* cose_data::cose_key::cbor() { - cbor_map* object = nullptr; - __try2 { - __try_new_catch_only(object, new cbor_map()); - if (nullptr == object) { - __leave2; - } - - cose_kty_t kty; - switch (_curve) { - case cose_ec_p256: - case cose_ec_p384: - case cose_ec_p521: - kty = cose_kty_t::cose_kty_ec2; - break; - default: - kty = cose_kty_t::cose_kty_okp; - break; - } - - if (_order.size()) { - for (cose_orderlist_t::iterator iter = _order.begin(); iter != _order.end(); iter++) { - int key = *iter; - switch (key) { - case cose_key_lable_t::cose_lable_kty: - *object << new cbor_pair(cose_key_lable_t::cose_lable_kty, new cbor_data(kty)); - break; - case cose_key_lable_t::cose_ec_crv: - *object << new cbor_pair(cose_key_lable_t::cose_ec_crv, new cbor_data(_curve)); - break; - case cose_key_lable_t::cose_ec_x: - *object << new cbor_pair(cose_key_lable_t::cose_ec_x, new cbor_data(_x)); - break; - case cose_key_lable_t::cose_ec_y: - if (_compressed) { - *object << new cbor_pair(cose_key_lable_t::cose_ec_y, new cbor_data(_ysign)); // y(-3) - } else { - *object << new cbor_pair(cose_key_lable_t::cose_ec_y, new cbor_data(_y)); // y(-3) - } - break; - default: - break; - } - } - } else { - *object << new cbor_pair(cose_key_lable_t::cose_lable_kty, new cbor_data(kty)) // kty(1) - << new cbor_pair(cose_key_lable_t::cose_ec_crv, new cbor_data(_curve)) // crv(-1) - << new cbor_pair(cose_key_lable_t::cose_ec_x, new cbor_data(_x)); // x(-2) - - if (cose_kty_t::cose_kty_ec2 == kty) { - if (_compressed) { - *object << new cbor_pair(cose_key_lable_t::cose_ec_y, new cbor_data(_ysign)); // y(-3) - } else { - *object << new cbor_pair(cose_key_lable_t::cose_ec_y, new cbor_data(_y)); // y(-3) - } - } - } - } - __finally2 { - // do nothing - } - return object; -} - -cose_data::cose_data() : _layer(nullptr) {} - -cose_data::~cose_data() { clear(); } - -cose_data& cose_data::set_owner(cose_recipient* layer) { - _layer = layer; - return *this; -} - -cose_recipient* cose_data::get_owner() { return _layer; } - -cose_data& cose_data::add_bool(int key, bool value) { - variant var; - _data_map.insert(std::make_pair(key, std::move(var.set_bool(value)))); - _order.push_back(key); - return *this; -} - -cose_data& cose_data::add(int key, int32 value) { - variant var; - _data_map.insert(std::make_pair(key, std::move(var.set_int32(value)))); - _order.push_back(key); - return *this; -} - -cose_data& cose_data::add(int key, const char* value) { - if (value) { - variant var; - _data_map.insert(std::make_pair(key, std::move(var.set_bstr_new((unsigned char*)value, strlen(value))))); - _order.push_back(key); - } - return *this; -} - -cose_data& cose_data::add(int key, const unsigned char* value, size_t size) { - variant var; - _data_map.insert(std::make_pair(key, std::move(var.set_bstr_new(value, size)))); - _order.push_back(key); - return *this; -} - -cose_data& cose_data::replace(int key, const unsigned char* value, size_t size) { - cose_variantmap_t::iterator iter = _data_map.find(key); - if (_data_map.end() != iter) { - variant var; - var.set_bstr_new(value, size); - iter->second = std::move(var); - } else { - variant var; - _data_map.insert(std::make_pair(key, std::move(var.set_bstr_new(value, size)))); - _order.push_back(key); - } - return *this; -} - -cose_data& cose_data::add(int key, std::string& value) { return add(key, (unsigned char*)value.c_str(), value.size()); } - -cose_data& cose_data::add(int key, const std::string& value) { return add(key, (unsigned char*)value.c_str(), value.size()); } - -cose_data& cose_data::add(int key, binary_t& value) { return add(key, &value[0], value.size()); } - -cose_data& cose_data::add(int key, const binary_t& value) { return add(key, &value[0], value.size()); } - -cose_data& cose_data::replace(int key, const binary_t& value) { return replace(key, &value[0], value.size()); } - -cose_data& cose_data::add(int key, uint16 curve, const binary_t& x, const binary_t& y) { - cose_key* k = nullptr; - return_t ret = errorcode_t::success; - __try2 { - __try_new_catch(k, new cose_key(), ret, __leave2); - - k->set(&get_owner()->get_static_key(), curve, x, y); - add(key, TYPE_STATIC_KEY, k); - - _keys.push_back(k); - } - __finally2 { - // do nothing - } - return *this; -} - -cose_data& cose_data::add(int key, uint16 curve, const binary_t& x, const binary_t& y, std::list& order) { - cose_key* k = nullptr; - return_t ret = errorcode_t::success; - __try2 { - __try_new_catch(k, new cose_key(), ret, __leave2); - - k->set(&get_owner()->get_static_key(), curve, x, y); - k->set(order); - add(key, TYPE_STATIC_KEY, k); - - _keys.push_back(k); - } - __finally2 { - // do nothing - } - return *this; -} - -cose_data& cose_data::add(int key, uint16 curve, const binary_t& x, bool ysign) { - cose_key* k = nullptr; - return_t ret = errorcode_t::success; - __try2 { - __try_new_catch(k, new cose_key(), ret, __leave2); - - k->set(&get_owner()->get_static_key(), curve, x, ysign); - add(key, TYPE_STATIC_KEY, k); - - _keys.push_back(k); - } - __finally2 { - // do nothing - } - return *this; -} - -cose_data& cose_data::add(int key, uint16 curve, const binary_t& x, bool ysign, std::list& order) { - cose_key* k = nullptr; - return_t ret = errorcode_t::success; - __try2 { - __try_new_catch(k, new cose_key(), ret, __leave2); - - k->set(&get_owner()->get_static_key(), curve, x, ysign); - k->set(order); - add(key, TYPE_STATIC_KEY, k); - - _keys.push_back(k); - } - __finally2 { - // do nothing - } - return *this; -} - -cose_data& cose_data::add(cose_alg_t alg, const char* kid, const binary_t& signature) { - cose_countersign* countersign = nullptr; - return_t ret = errorcode_t::success; - - __try2 { - __try_new_catch(countersign, new cose_countersign, ret, __leave2); - countersign->set_upperlayer(get_owner()); - countersign->set_property(cose_property_t::cose_property_countersign); - - countersign->get_protected().add(cose_key_t::cose_alg, alg); - if (kid) { - countersign->get_unprotected().add(cose_key_t::cose_kid, kid); - } - countersign->get_signature().set(signature); - - add(countersign); - } - __finally2 { - // do nothing - } - return *this; -} - -cose_data& cose_data::add(cose_recipient* countersign) { - return_t ret = errorcode_t::success; - - __try2 { - cose_countersigns* countersigns = get_owner()->get_countersigns1(); - cose_variantmap_t::iterator iter = _data_map.find(cose_key_t::cose_counter_sig); - if (_data_map.end() == iter) { - add(cose_key_t::cose_counter_sig, TYPE_COUNTER_SIG, countersigns); - } - countersigns->add(countersign); - } - __finally2 { - // do nothing - } - return *this; -} - -cose_data& cose_data::add(int key, vartype_t vty, void* p) { - if (p) { - variant vt; - _data_map.insert(std::make_pair(key, std::move(vt.set_user_type(vty, p)))); - _order.push_back(key); - } - return *this; -} - -cose_data& cose_data::add(int key, variant& value) { - _data_map.insert(std::make_pair(key, value)); - _order.push_back(key); - return *this; -} - -cose_data& cose_data::set(const binary_t& bin) { - _payload = bin; - return *this; -} - -cose_data& cose_data::set(const std::string& value) { - _payload = convert(value); - return *this; -} - -cose_data& cose_data::set_b16(std::string const value) { - _payload = base16_decode(value); - return *this; -} - -cose_data& cose_data::set_b16(const char* value) { - if (value) { - _payload = base16_decode(value, strlen(value)); - } - return *this; -} - -cose_data& cose_data::clear() { - _data_map.clear(); - _order.clear(); - _payload.clear(); - for (std::list::iterator it = _keys.begin(); it != _keys.end(); it++) { - cose_key* object = *it; - delete object; - } - _keys.clear(); - return *this; -} - -bool cose_data::exist(int key) { - bool ret_value = false; - return_t ret = errorcode_t::success; - - std::map::iterator iter = _data_map.find(key); - if (_data_map.end() != iter) { - ret_value = true; - } - return ret_value; -} - -return_t cose_data::finditem(int key, int& value) { - return_t ret = errorcode_t::success; - - std::map::iterator iter = _data_map.find(key); - if (_data_map.end() == iter) { - ret = errorcode_t::not_found; - } else { - value = iter->second.to_int(); - } - return ret; -} - -return_t cose_data::finditem(int key, std::string& value) { - return_t ret = errorcode_t::success; - - std::map::iterator iter = _data_map.find(key); - if (_data_map.end() == iter) { - ret = errorcode_t::not_found; - } else { - iter->second.to_string(value); - } - return ret; -} - -return_t cose_data::finditem(int key, binary_t& value) { - return_t ret = errorcode_t::success; - variant vt; - - std::map::iterator iter = _data_map.find(key); - if (_data_map.end() == iter) { - ret = errorcode_t::not_found; - } else { - iter->second.to_binary(value); - } - return ret; -} - -return_t cose_data::build_protected(cbor_data** object) { - return_t ret = errorcode_t::success; - cbor_map* part_protected = nullptr; - - __try2 { - if (nullptr == object) { - ret = errorcode_t::invalid_parameter; - __leave2; - } - - if (_payload.size()) { - *object = new cbor_data(_payload); - } else { - if (_data_map.size()) { - __try_new_catch(part_protected, new cbor_map(), ret, __leave2); - - cose_orderlist_t::iterator list_iter; - for (list_iter = _order.begin(); list_iter != _order.end(); list_iter++) { - int key = *list_iter; - - cose_variantmap_t::iterator map_iter = _data_map.find(key); - variant value = map_iter->second; - *part_protected << new cbor_pair(new cbor_data(key), new cbor_data(std::move(value))); - } - - cbor_publisher publisher; - publisher.publish(part_protected, &_payload); - - *object = new cbor_data(_payload); - } else { - *object = new cbor_data(binary_t()); - } - } - } - __finally2 { - if (part_protected) { - part_protected->release(); - } - } - return ret; -} - -return_t cose_data::build_protected(cbor_data** object, cose_variantmap_t& unsent) { - return_t ret = errorcode_t::success; - cbor_map* part_protected = nullptr; - - __try2 { - if (nullptr == object) { - ret = errorcode_t::invalid_parameter; - __leave2; - } - - if (_payload.size()) { - *object = new cbor_data(_payload); - } else { - if (_data_map.size()) { - __try_new_catch(part_protected, new cbor_map(), ret, __leave2); - - cose_orderlist_t::iterator list_iter; - for (list_iter = _order.begin(); list_iter != _order.end(); list_iter++) { - int key = *list_iter; - - cose_variantmap_t::iterator unsent_iter = unsent.find(key); - if (unsent.end() != unsent_iter) { - continue; - } - - cose_variantmap_t::iterator map_iter = _data_map.find(key); - variant value = map_iter->second; - *part_protected << new cbor_pair(new cbor_data(key), new cbor_data(std::move(value))); - } - - cbor_publisher publisher; - publisher.publish(part_protected, &_payload); - - *object = new cbor_data(_payload); - } else { - *object = new cbor_data(binary_t()); - } - } - } - __finally2 { - if (part_protected) { - part_protected->release(); - } - } - return ret; -} - -return_t cose_data::build_unprotected(cbor_map** object) { - return_t ret = errorcode_t::success; - cbor_map* part_unprotected = nullptr; - - __try2 { - if (nullptr == object) { - ret = errorcode_t::invalid_parameter; - __leave2; - } - - __try_new_catch(part_unprotected, new cbor_map(), ret, __leave2); - - cose_orderlist_t::iterator list_iter; - for (list_iter = _order.begin(); list_iter != _order.end(); list_iter++) { - int key = *list_iter; - - cose_variantmap_t::iterator map_iter = _data_map.find(key); - variant value = map_iter->second; - variant_t& vt = value.content(); - - if (TYPE_STATIC_KEY == vt.type) { - cose_key* k = (cose_key*)vt.data.p; - *part_unprotected << new cbor_pair(key, k->cbor()); - } else if (TYPE_COUNTER_SIG == vt.type) { - cose_countersigns* signs = get_owner()->get_countersigns1(); - *part_unprotected << new cbor_pair(cose_key_t::cose_counter_sig, signs->cbor()); - } else { - *part_unprotected << new cbor_pair(new cbor_data(key), new cbor_data(value)); - } - } - - *object = part_unprotected; - } - __finally2 { - // do nothing - } - return ret; -} - -return_t cose_data::build_unprotected(cbor_map** object, cose_variantmap_t& unsent) { - return_t ret = errorcode_t::success; - cbor_map* part_unprotected = nullptr; - - __try2 { - if (nullptr == object) { - ret = errorcode_t::invalid_parameter; - __leave2; - } - - __try_new_catch(part_unprotected, new cbor_map(), ret, __leave2); - - cose_orderlist_t::iterator list_iter; - for (list_iter = _order.begin(); list_iter != _order.end(); list_iter++) { - int key = *list_iter; - - cose_variantmap_t::iterator unsent_iter = unsent.find(key); - if (unsent.end() != unsent_iter) { - continue; - } - - cose_variantmap_t::iterator map_iter = _data_map.find(key); - variant value = map_iter->second; - variant_t& vt = value.content(); - - if (TYPE_STATIC_KEY == vt.type) { - cose_key* k = (cose_key*)vt.data.p; - *part_unprotected << new cbor_pair(key, k->cbor()); - } else if (TYPE_COUNTER_SIG == vt.type) { - cose_recipient* sign = (cose_recipient*)vt.data.p; - *part_unprotected << new cbor_pair(cose_key_t::cose_counter_sig, sign->cbor()); - } else { - *part_unprotected << new cbor_pair(new cbor_data(key), new cbor_data(value)); - } - } - - *object = part_unprotected; - } - __finally2 { - // do nothing - } - return ret; -} - -return_t cose_data::build_data(cbor_data** object) { - return_t ret = errorcode_t::success; - - __try2 { - if (nullptr == object) { - ret = errorcode_t::invalid_parameter; - __leave2; - } - - __try_new_catch(*object, new cbor_data(_payload), ret, __leave2); - } - __finally2 { - // do nothing - } - return ret; -} - -return_t cose_data::parse_protected(cbor_data* object) { - return_t ret = errorcode_t::success; - cbor_object* root = nullptr; - - __try2 { - if (nullptr == object) { - ret = errorcode_t::invalid_parameter; - __leave2; - } - - object->data().to_binary(_payload); - - if (0 == _payload.size()) { - __leave2; - } - - ret = cbor_parse(&root, _payload); - if (errorcode_t::success != ret) { - __leave2; - } - cbor_map* datamap = cbor_typeof(root, cbor_type_t::cbor_type_map); - if (nullptr == datamap) { - ret = errorcode_t::bad_format; - __leave2; - } - - ret = parse(datamap); - } - __finally2 { - if (root) { - root->release(); - } - } - return ret; -} - -return_t cose_data::parse_unprotected(cbor_map* object) { - return_t ret = errorcode_t::success; - - __try2 { - if (nullptr == object) { - ret = errorcode_t::invalid_parameter; - __leave2; - } - - ret = parse(object); - } - __finally2 { - // do nothing - } - return ret; -} - -return_t cose_data::parse_payload(cbor_data* object) { - return_t ret = errorcode_t::success; - - __try2 { - if (nullptr == object) { - ret = errorcode_t::invalid_parameter; - __leave2; - } - - object->data().to_binary(_payload); - } - __finally2 { - // do nothing - } - return ret; -} - -return_t cose_data::parse(cbor_map* object) { - return_t ret = errorcode_t::success; - return_t check = errorcode_t::success; - - __try2 { - if (nullptr == object) { - ret = errorcode_t::invalid_parameter; - __leave2; - } - - size_t size_map = object->size(); - for (size_t i = 0; i < size_map; i++) { - cbor_pair* pair = (*object)[i]; - - cbor_data* pair_key = pair->left(); - int keyid = 0; - keyid = pair_key->data().to_int(); - - cbor_object* pair_value = pair->right(); - - cbor_data* data = cbor_typeof(pair_value, cbor_type_t::cbor_type_data); - if (data) { - add(keyid, data->data()); - continue; - } - - cbor_simple* simple = cbor_typeof(pair_value, cbor_type_t::cbor_type_simple); - if (simple) { - cbor_simple_t simple_type = simple->simple_type(); - switch (simple_type) { - case cbor_simple_true: - add_bool(keyid, true); - break; - case cbor_simple_false: - add_bool(keyid, false); - break; - default: - break; - } - continue; - } - - cbor_map* map = cbor_typeof(pair_value, cbor_type_t::cbor_type_map); - if (map) { - parse_static_key(map, keyid); - continue; - } - - cbor_array* array = cbor_typeof(pair_value, cbor_type_t::cbor_type_array); - if (array) { - switch (keyid) { - case cose_counter_sig: // (7) - { - cbor_data* countersig_protected = cbor_typeof((*array)[0], cbor_type_t::cbor_type_data); - if (countersig_protected) { - parse_counter_signs(array, keyid); - } else { - cbor_array* countersigns = cbor_typeof((*array)[0], cbor_type_t::cbor_type_array); - if (countersigns) { - for (size_t size = 0; size < countersigns->size(); size++) { - cbor_array* countersign = cbor_typeof((*array)[size], cbor_type_t::cbor_type_array); - parse_counter_signs(countersign, keyid); - } - } - } - } break; - case cose_crit: // (2) - default: - break; - } - continue; - } - } - } - __finally2 { - // do nothing - } - return ret; -} - -return_t cose_data::parse_static_key(cbor_map* object, int keyid) { - return_t ret = errorcode_t::success; - return_t check = errorcode_t::success; - - __try2 { - if (nullptr == object) { - ret = errorcode_t::invalid_parameter; - __leave2; - } - - cbor_map_hint> hint(object); - cose_orderlist_t order; - uint16 kty = 0; - uint16 curve = 0; - binary_t bin_x; - binary_t bin_y; - - cbor_object* cbor_curve = nullptr; - cbor_object* cbor_x = nullptr; - cbor_object* cbor_y = nullptr; - - hint.find(cose_key_lable_t::cose_ec_crv, &cbor_curve); - hint.find(cose_key_lable_t::cose_ec_x, &cbor_x); - hint.find(cose_key_lable_t::cose_ec_y, &cbor_y); - hint.get_order(order); - - if (cbor_curve && cbor_x) { - cbor_data* cbor_data_curve = cbor_typeof(cbor_curve, cbor_type_t::cbor_type_data); - cbor_data* cbor_data_x = cbor_typeof(cbor_x, cbor_type_t::cbor_type_data); - cbor_data* cbor_data_y = cbor_typeof(cbor_y, cbor_type_t::cbor_type_data); - cbor_simple* cbor_simple_y = cbor_typeof(cbor_y, cbor_type_t::cbor_type_simple); - - curve = cbor_data_curve->data().to_int(); - cbor_data_x->data().to_binary(bin_x); - - switch (curve) { - case cose_ec_p256: - case cose_ec_p384: - case cose_ec_p521: - if (cbor_data_y) { - cbor_data_y->data().to_binary(bin_y); - add(keyid, curve, bin_x, bin_y, order); - } else if (cbor_simple_y) { - add(keyid, curve, bin_x, cbor_simple_true == cbor_simple_y->simple_type(), order); - } else { - ret = errorcode_t::bad_format; - } - break; - case cose_ec_x25519: - case cose_ec_x448: - case cose_ec_ed25519: - case cose_ec_ed448: - add(keyid, curve, bin_x, bin_y, order); - break; - } - - cbor_curve->release(); - cbor_x->release(); - } - - if (cbor_y) { - cbor_y->release(); - } - } - __finally2 { - // do nothing - } - return ret; -} - -return_t cose_data::parse_counter_signs(cbor_array* object, int keyid) { - return_t ret = errorcode_t::success; - __try2 { - if (nullptr == object) { - ret = errorcode_t::invalid_parameter; - __leave2; - } - - if (object->size() == 3) { - cbor_data* countersig_protected = cbor_typeof((*object)[0], cbor_type_t::cbor_type_data); - cbor_map* countersig_unprotected = cbor_typeof((*object)[1], cbor_type_t::cbor_type_map); - cbor_data* countersig_signature = cbor_typeof((*object)[2], cbor_type_t::cbor_type_data); - if (countersig_protected && countersig_unprotected && countersig_signature) { - cose_countersign* countersign = nullptr; - __try_new_catch_only(countersign, new cose_countersign); - - countersign->set_upperlayer(get_owner()); - countersign->set_composer(get_owner()->get_composer()); - countersign->set_property(cose_property_t::cose_property_countersign); - - countersign->get_protected().set(countersig_protected); - countersign->get_unprotected().set(countersig_unprotected); // keep order - countersign->get_signature().set(countersig_signature); - - add(countersign); - } - } - } - __finally2 { - // do nothing - } - return ret; -} - -bool cose_data::empty_binary() { return 0 == _payload.size(); } - -size_t cose_data::size_binary() { return _payload.size(); } - -void cose_data::get_binary(binary_t& bin) { bin = _payload; } - -cose_protected::cose_protected() {} - -cose_protected::~cose_protected() {} - -cose_protected& cose_protected::add(cose_key_t key, uint32 value) { - _protected.add(key, value); - return *this; -} - -cose_protected& cose_protected::set(const binary_t& bin) { - _protected.set(bin); - cbor_object* root = nullptr; - cbor_parse(&root, bin); - if (root) { - cbor_data* object = cbor_typeof(root, cbor_type_t::cbor_type_data); - if (object) { - set(object); - } - root->release(); - } - return *this; -} - -return_t cose_protected::set(cbor_data* object) { return _protected.parse_protected(object); } - -cose_data& cose_protected::data() { return _protected; } - -cose_protected& cose_protected::clear() { - _protected.clear(); - return *this; -} - -cbor_data* cose_protected::cbor() { - cbor_data* object = nullptr; - _protected.build_protected(&object); - return object; -} - -cose_unprotected::cose_unprotected() {} - -cose_unprotected::~cose_unprotected() {} - -cose_unprotected& cose_unprotected::add(cose_key_t key, int32 value) { - _unprotected.add(key, value); - return *this; -} - -cose_unprotected& cose_unprotected::add(cose_key_t key, const char* value) { - _unprotected.add(key, value); - return *this; -} - -cose_unprotected& cose_unprotected::add(cose_key_t key, std::string& value) { - _unprotected.add(key, value); - return *this; -} - -cose_unprotected& cose_unprotected::add(cose_key_t key, const std::string& value) { - _unprotected.add(key, value); - return *this; -} - -cose_unprotected& cose_unprotected::add(cose_key_t key, binary_t& value) { - _unprotected.add(key, value); - return *this; -} - -cose_unprotected& cose_unprotected::add(cose_key_t key, const binary_t& value) { - _unprotected.add(key, value); - return *this; -} - -cose_unprotected& cose_unprotected::add(cose_key_t key, uint16 curve, const binary_t& x, const binary_t& y) { - _unprotected.add(key, curve, x, y); - return *this; -} - -cose_unprotected& cose_unprotected::add(cose_key_t key, uint16 curve, const binary_t& x, bool ysign) { - _unprotected.add(key, curve, x, ysign); - return *this; -} - -cose_unprotected& cose_unprotected::add(cose_alg_t alg, const char* kid, const binary_t& signature) { - _unprotected.add(alg, kid, signature); - return *this; -} - -return_t cose_unprotected::set(cbor_map* object) { return _unprotected.parse_unprotected(object); } - -cose_data& cose_unprotected::data() { return _unprotected; } - -cose_unprotected& cose_unprotected::clear() { - _unprotected.clear(); - return *this; -} - -cbor_map* cose_unprotected::cbor() { - cbor_map* object = nullptr; - _unprotected.build_unprotected(&object); - return object; -} - -cose_binary::cose_binary() {} - -cose_binary& cose_binary::set_b16(const char* value) { - _payload.set_b16(value); - return *this; -} - -cose_binary& cose_binary::set_b16(const std::string& value) { - _payload.set_b16(value); - return *this; -} - -cose_binary& cose_binary::set(const std::string& value) { - _payload.set(value); - return *this; -} - -cose_binary& cose_binary::set(const binary_t& value) { - _payload.set(value); - return *this; -} - -return_t cose_binary::set(cbor_data* object) { return _payload.parse_payload(object); } - -cose_data& cose_binary::data() { return _payload; } - -bool cose_binary::empty() { return _payload.empty_binary(); } - -size_t cose_binary::size() { return _payload.size_binary(); } - -void cose_binary::get(binary_t& bin) { _payload.get_binary(bin); } - -cose_binary& cose_binary::clear() { - _payload.clear(); - return *this; -} - -cbor_data* cose_binary::cbor() { - cbor_data* object = nullptr; - _payload.build_data(&object); - return object; -} - -cose_recipient::cose_recipient() - : _upperlayer(nullptr), - _depth(0), - _property(cose_property_t::cose_property_normal), - _composer(nullptr), - _cbor_tag(cbor_tag_t::cbor_tag_unknown), - _countersigns(nullptr) { - get_protected().data().set_owner(this); - get_unprotected().data().set_owner(this); - get_payload().data().set_owner(this); - get_singleitem().data().set_owner(this); - get_recipients().set_upperlayer(this); -} - -cose_recipient::~cose_recipient() { - if (_countersigns) { - delete _countersigns; - } -} - -void cose_recipient::set_upperlayer(cose_recipient* layer) { - _upperlayer = layer; - set_composer(layer->get_composer()); - - if (layer) { - _depth = layer->get_depth() + 1; - } -} - -cose_recipient* cose_recipient::get_upperlayer() { return _upperlayer; } - -cose_recipient* cose_recipient::get_upperlayer2() { - cose_recipient* layer = nullptr; - if (_upperlayer) { - layer = _upperlayer; - } else { - layer = this; // aka body, composer.get_layer() - } - return layer; -} - -uint16 cose_recipient::get_depth() { return _depth; } - -void cose_recipient::set_composer(cose_composer* composer) { _composer = composer; } - -cose_composer* cose_recipient::get_composer() { return _composer; } - -cose_recipient& cose_recipient::set_property(uint16 property) { - _property = property; - return *this; -} - -uint16 cose_recipient::get_property() { return _property; } - -cose_recipient& cose_recipient::add(cose_recipient* recipient) { - cose_recipient* object = recipient; - if (nullptr == object) { - object = new cose_recipient; - } - - object->set_upperlayer(this); - object->set_composer(get_composer()); - - return _recipients.add(object); -} - -return_t cose_recipient::finditem(int key, int& value, int scope) { - return_t ret = errorcode_t::not_found; - __try2 { - if (cose_scope::cose_scope_unsent & scope) { - ret = get_composer()->get_unsent().data().finditem(key, value); - if (errorcode_t::success == ret) { - __leave2; - } - } - if (cose_scope::cose_scope_protected & scope) { - ret = get_protected().data().finditem(key, value); - if (errorcode_t::success == ret) { - __leave2; - } - } - if (cose_scope::cose_scope_unprotected & scope) { - ret = get_unprotected().data().finditem(key, value); - if (errorcode_t::success == ret) { - __leave2; - } - } - if (cose_scope::cose_scope_children & scope) { - ret = get_recipients().finditem(key, value, scope); - } - } - __finally2 { - // do nothing - } - return ret; -} - -return_t cose_recipient::finditem(int key, std::string& value, int scope) { - return_t ret = errorcode_t::not_found; - __try2 { - if (cose_scope::cose_scope_unsent & scope) { - ret = get_composer()->get_unsent().data().finditem(key, value); - if (errorcode_t::success == ret) { - __leave2; - } - } - if (cose_scope::cose_scope_protected & scope) { - ret = get_protected().data().finditem(key, value); - if (errorcode_t::success == ret) { - __leave2; - } - } - if (cose_scope::cose_scope_unprotected & scope) { - ret = get_unprotected().data().finditem(key, value); - if (errorcode_t::success == ret) { - __leave2; - } - } - if (cose_scope::cose_scope_children & scope) { - ret = get_recipients().finditem(key, value, scope); - if (errorcode_t::success == ret) { - __leave2; - } - } - } - __finally2 { - // do nothing - } - return ret; -} - -return_t cose_recipient::finditem(int key, binary_t& value, int scope) { - return_t ret = errorcode_t::not_found; - __try2 { - if (cose_scope::cose_scope_unsent & scope) { - ret = get_composer()->get_unsent().data().finditem(key, value); - if (errorcode_t::success == ret) { - __leave2; - } - } - if (cose_scope::cose_scope_params & scope) { - ret = get_params().finditem(key, value); - if (errorcode_t::success == ret) { - __leave2; - } - } - if (cose_scope::cose_scope_protected & scope) { - ret = get_protected().data().finditem(key, value); - if (errorcode_t::success == ret) { - __leave2; - } - } - if (cose_scope::cose_scope_unprotected & scope) { - ret = get_unprotected().data().finditem(key, value); - if (errorcode_t::success == ret) { - __leave2; - } - } - if (cose_scope::cose_scope_children & scope) { - ret = get_recipients().finditem(key, value, scope); - } - } - __finally2 { - // do nothing - } - return ret; -} - -return_t cose_recipient::setparam(cose_param_t id, const binary_t& bin) { - return_t ret = errorcode_t::success; - __try2 { - switch (id) { - case cose_param_t::cose_param_cek: - case cose_param_t::cose_param_ciphertext: - case cose_param_t::cose_param_secret: - case cose_param_t::cose_param_plaintext: - get_params().replace(id, bin); - break; - default: - ret = errorcode_t::request; - break; - } - } - __finally2 { - // do nothing - } - return ret; -} - -return_t cose_recipient::getparam(cose_param_t id, binary_t& bin) { - return_t ret = errorcode_t::success; - __try2 { - switch (id) { - case cose_param_t::cose_param_cek: - case cose_param_t::cose_param_ciphertext: - case cose_param_t::cose_param_secret: - case cose_param_t::cose_param_plaintext: - get_params().replace(id, bin); - break; - default: - ret = errorcode_t::request; - break; - } - } - __finally2 { - // do nothing - } - return ret; -} - -return_t cose_recipient::parse(cbor_array* root) { - return_t ret = errorcode_t::success; - crypto_advisor* advisor = crypto_advisor::get_instance(); - cbor_tag_t cbor_tag = cbor_tag_t::cbor_tag_unknown; - - __try2 { - clear(); - - if (nullptr == root) { - ret = errorcode_t::invalid_parameter; - __leave2; - } - - ret = parse_header(root); - if (errorcode_t::success != ret) { - __leave2; - } - - ret = parse_message(root); - if (errorcode_t::success != ret) { - __leave2; - } - } - __finally2 { - // do nothing - if (errorcode_t::success != ret) { - // throw; - } - } - return ret; -} - -return_t cose_recipient::parse_header(cbor_array* root) { - return_t ret = errorcode_t::success; - - __try2 { - if (nullptr == root) { - ret = errorcode_t::invalid_parameter; - __leave2; - } - - size_t size_message = root->size(); - - if (size_message < 3) { - ret = errorcode_t::bad_format; - __leave2; - } - - // parse protected and unprotected - ret = parse_protected((*root)[0]); - if (errorcode_t::success != ret) { - __leave2; - } - - ret = parse_unprotected((*root)[1]); - if (errorcode_t::success != ret) { - __leave2; - } - - ret = parse_payload((*root)[2]); - if (errorcode_t::success != ret) { - __leave2; - } - } - __finally2 { - // do nothing - } - return ret; -} - -return_t cose_recipient::parse_message(cbor_array* root) { - return_t ret = errorcode_t::success; - crypto_advisor* advisor = crypto_advisor::get_instance(); - size_t i = 0; - - __try2 { - if (nullptr == root) { - ret = errorcode_t::invalid_parameter; - __leave2; - } - - size_t size_message = root->size(); - for (i = 3; i < size_message; i++) { - cbor_object* cbor_item = (*root)[i]; - - // in case of cose_tag_mac/cose_tag_mac0 - cbor_data* cbor_singleitem = cbor_typeof(cbor_item, cbor_type_t::cbor_type_data); - if (cbor_singleitem) { - parse_singleitem(cbor_item); - continue; - } - - // in case of cose_tag_encrypt/cose_tag_mac/cose_tag_sign - cbor_array* cbor_recipients = cbor_typeof(cbor_item, cbor_type_t::cbor_type_array); - if (cbor_recipients) { - for (size_t size = 0; size < cbor_recipients->size(); size++) { - cbor_array* cbor_recipient = cbor_typeof((*cbor_recipients)[size], cbor_type_t::cbor_type_array); - if (cbor_recipient) { - add().parse(cbor_recipient); - } - } - continue; - } - } - } - __finally2 { - // do nothing - } - return ret; -} - -return_t cose_recipient::parse_protected(cbor_object* object) { - return_t ret = errorcode_t::success; - - __try2 { - if (nullptr == object) { - ret = errorcode_t::invalid_parameter; - __leave2; - } - - cbor_data* cbor_protected = cbor_typeof(object, cbor_type_t::cbor_type_data); - if (nullptr == cbor_protected) { - ret = errorcode_t::bad_format; - __leave2; - } - - ret = get_protected().set(cbor_protected); - } - __finally2 { - // do nothing - } - return ret; -} - -return_t cose_recipient::parse_unprotected(cbor_object* object) { - return_t ret = errorcode_t::success; - __try2 { - if (nullptr == object) { - ret = errorcode_t::invalid_parameter; - __leave2; - } - - cbor_map* cbor_unprotected = cbor_typeof(object, cbor_type_t::cbor_type_map); - if (nullptr == cbor_unprotected) { - ret = errorcode_t::bad_format; - __leave2; - } - - ret = get_unprotected().set(cbor_unprotected); - } - __finally2 { - // do nothing - } - return ret; -} - -return_t cose_recipient::parse_payload(cbor_object* object) { - return_t ret = errorcode_t::success; - - __try2 { - if (nullptr == object) { - ret = errorcode_t::invalid_parameter; - __leave2; - } - - cbor_data* cbor_payload = cbor_typeof(object, cbor_type_t::cbor_type_data); - if (nullptr == cbor_payload) { - ret = errorcode_t::bad_format; - __leave2; - } - - ret = get_payload().set(cbor_payload); - } - __finally2 { - // do nothing - } - return ret; -} - -return_t cose_recipient::parse_singleitem(cbor_object* object) { - return_t ret = errorcode_t::success; - - __try2 { - if (nullptr == object) { - ret = errorcode_t::invalid_parameter; - __leave2; - } - - cbor_data* cbor_singleitem = cbor_typeof(object, cbor_type_t::cbor_type_data); - if (nullptr == cbor_singleitem) { - ret = errorcode_t::bad_format; - __leave2; - } - - ret = get_singleitem().set(cbor_singleitem); - } - __finally2 { - // do nothing - } - return ret; -} - -cose_protected& cose_recipient::get_protected() { return _protected; } - -cose_unprotected& cose_recipient::get_unprotected() { return _unprotected; } - -cose_binary& cose_recipient::get_payload() { return _payload; } - -cose_binary& cose_recipient::get_singleitem() { return _singleitem; } - -cose_binary& cose_recipient::get_signature() { return _singleitem; } - -cose_binary& cose_recipient::get_tag() { return _singleitem; } - -cose_recipients& cose_recipient::get_recipients() { return _recipients; } - -cose_data& cose_recipient::get_params() { return _params; } - -crypto_key& cose_recipient::get_static_key() { return _static_key; } - -cose_countersigns* cose_recipient::get_countersigns0() { return _countersigns; } - -cose_countersigns* cose_recipient::get_countersigns1() { - if (nullptr == _countersigns) { - _countersigns = new cose_countersigns; - _countersigns->set_upperlayer(this); - } - return _countersigns; -} - -cose_recipient& cose_recipient::clear() { - _cbor_tag = cbor_tag_t::cbor_tag_unknown; - get_protected().clear(); - get_unprotected().clear(); - get_payload().clear(); - get_singleitem().clear(); - get_recipients().clear(); - if (_countersigns) { - delete _countersigns; - _countersigns = nullptr; - } - get_static_key().clear(); - get_params().clear(); - return *this; -} - -cose_alg_t cose_recipient::get_algorithm() { - int alg = cose_alg_t::cose_unknown; - get_protected().data().finditem(cose_key_t::cose_alg, alg); - if (cose_alg_t::cose_unknown == alg) { - get_unprotected().data().finditem(cose_key_t::cose_alg, alg); - } - return (cose_alg_t)alg; -} - -std::string cose_recipient::get_kid() { - std::string kid; - get_unprotected().data().finditem(cose_key_t::cose_kid, kid); - return kid; -} - -void cose_recipient::for_each(void (*for_each_handler)(cose_layer*, void* userdata), void* userdata) { - if (for_each_handler) { - for_each_handler(this, userdata); - _recipients.for_each(for_each_handler, userdata); - } -} - -cbor_array* cose_recipient::cbor() { - cbor_array* object = new cbor_array; - *object << get_protected().cbor() << get_unprotected().cbor() << get_payload().cbor(); - if (_recipients.size()) { - *object << _recipients.cbor(); - } - return object; -} - -cose_recipients::cose_recipients() : _upperlayer(nullptr) {} - -cose_recipients::~cose_recipients() { clear(); } - -cose_recipient& cose_recipients::add(cose_recipient* recipient) { - recipient->set_upperlayer(get_upperlayer()); - std::list::iterator iter = _recipients.insert(_recipients.end(), recipient); - return **iter; -} - -cose_recipients& cose_recipients::clear() { - for (std::list::iterator iter = _recipients.begin(); iter != _recipients.end(); iter++) { - cose_recipient* item = *iter; - delete item; - } - _recipients.clear(); - return *this; -} - -bool cose_recipients::empty() { return (0 == _recipients.size()); } - -size_t cose_recipients::size() { return _recipients.size(); } - -cose_recipient* cose_recipients::operator[](size_t index) { - cose_recipient* object = nullptr; - if (index < _recipients.size()) { - std::list::iterator iter = _recipients.begin(); - std::advance(iter, index); - object = *iter; - } - return object; -} - -void cose_recipients::for_each(void (*for_each_handler)(cose_layer*, void* userdata), void* userdata) { - if (for_each_handler) { - std::list::iterator iter; - for (iter = _recipients.begin(); iter != _recipients.end(); iter++) { - cose_recipient* item = *iter; - item->for_each(for_each_handler, userdata); - } - } -} - -cose_recipients& cose_recipients::set_upperlayer(cose_recipient* layer) { - _upperlayer = layer; - return *this; -} - -cose_recipient* cose_recipients::get_upperlayer() { return _upperlayer; } - -return_t cose_recipients::finditem(int key, int& value, int scope) { - return_t ret = errorcode_t::not_found; - std::list::iterator iter; - for (iter = _recipients.begin(); iter != _recipients.end(); iter++) { - cose_recipient* item = *iter; - ret = item->finditem(key, value, scope); - if (errorcode_t::success == ret) { - break; - } - } - return ret; -} - -return_t cose_recipients::finditem(int key, std::string& value, int scope) { - return_t ret = errorcode_t::not_found; - std::list::iterator iter; - for (iter = _recipients.begin(); iter != _recipients.end(); iter++) { - cose_recipient* item = *iter; - ret = item->finditem(key, value, scope); - if (errorcode_t::success == ret) { - break; - } - } - return ret; -} - -return_t cose_recipients::finditem(int key, binary_t& value, int scope) { - return_t ret = errorcode_t::not_found; - std::list::iterator iter; - for (iter = _recipients.begin(); iter != _recipients.end(); iter++) { - cose_recipient* item = *iter; - ret = item->finditem(key, value, scope); - if (errorcode_t::success == ret) { - break; - } - } - return ret; -} - -cbor_array* cose_recipients::cbor() { - cbor_array* object = new cbor_array; - std::list::iterator iter; - for (iter = _recipients.begin(); iter != _recipients.end(); iter++) { - cose_recipient* item = *iter; - *object << item->cbor(); - } - return object; -} - -cose_unsent::cose_unsent() {} - -cose_unsent::~cose_unsent() {} - -cose_data& cose_unsent::data() { return _unsent; } - -bool cose_unsent::isvalid(int key) { - bool ret = true; - switch (key) { - case cose_param_t::cose_external: - case cose_param_t::cose_unsent_apu_id: - case cose_param_t::cose_unsent_apu_nonce: - case cose_param_t::cose_unsent_apu_other: - case cose_param_t::cose_unsent_apv_id: - case cose_param_t::cose_unsent_apv_nonce: - case cose_param_t::cose_unsent_apv_other: - case cose_param_t::cose_unsent_pub_other: - case cose_param_t::cose_unsent_priv_other: - case cose_param_t::cose_unsent_iv: - case cose_param_t::cose_unsent_alg: - case cose_param_t::cose_param_cek: - break; - default: - ret = false; - break; - } - return ret; -} - -cose_unsent& cose_unsent::add(int key, const char* value) { - if (value && isvalid(key)) { - _unsent.add(key, value); - } - return *this; -} - -cose_unsent& cose_unsent::add(int key, const unsigned char* value, size_t size) { - if (value && isvalid(key)) { - _unsent.add(key, value, size); - } - return *this; -} - -cose_unsent& cose_unsent::add(int key, binary_t& value) { - if (isvalid(key)) { - _unsent.add(key, value); - } - return *this; -} - -cose_unsent& cose_unsent::add(int key, const binary_t& value) { - if (isvalid(key)) { - _unsent.add(key, value); - } - return *this; -} - cose_composer::cose_composer() : _cbor_tag(cbor_tag_t::cbor_tag_unknown) { get_layer().set_composer(this); } return_t cose_composer::compose(cbor_array** object, bool tagged) { diff --git a/sdk/crypto/cose/cose_data.cpp b/sdk/crypto/cose/cose_data.cpp new file mode 100644 index 0000000..b2c7107 --- /dev/null +++ b/sdk/crypto/cose/cose_data.cpp @@ -0,0 +1,749 @@ +/* vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab smarttab : */ +/** + * @file {file} + * @author Soo Han, Kim (princeb612.kr@gmail.com) + * @desc + * + * Revision History + * Date Name Description + * + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace hotplace { +using namespace io; +namespace crypto { + +#define TYPE_STATIC_KEY (TYPE_USER) +#define TYPE_COUNTER_SIG (vartype_t)(TYPE_USER + 1) + +cose_data::cose_data() : _layer(nullptr) {} + +cose_data::~cose_data() { clear(); } + +cose_data& cose_data::set_owner(cose_recipient* layer) { + _layer = layer; + return *this; +} + +cose_recipient* cose_data::get_owner() { return _layer; } + +cose_data& cose_data::add_bool(int key, bool value) { + variant var; + _data_map.insert(std::make_pair(key, std::move(var.set_bool(value)))); + _order.push_back(key); + return *this; +} + +cose_data& cose_data::add(int key, int32 value) { + variant var; + _data_map.insert(std::make_pair(key, std::move(var.set_int32(value)))); + _order.push_back(key); + return *this; +} + +cose_data& cose_data::add(int key, const char* value) { + if (value) { + variant var; + _data_map.insert(std::make_pair(key, std::move(var.set_bstr_new((unsigned char*)value, strlen(value))))); + _order.push_back(key); + } + return *this; +} + +cose_data& cose_data::add(int key, const unsigned char* value, size_t size) { + variant var; + _data_map.insert(std::make_pair(key, std::move(var.set_bstr_new(value, size)))); + _order.push_back(key); + return *this; +} + +cose_data& cose_data::replace(int key, const unsigned char* value, size_t size) { + cose_variantmap_t::iterator iter = _data_map.find(key); + if (_data_map.end() != iter) { + variant var; + var.set_bstr_new(value, size); + iter->second = std::move(var); + } else { + variant var; + _data_map.insert(std::make_pair(key, std::move(var.set_bstr_new(value, size)))); + _order.push_back(key); + } + return *this; +} + +cose_data& cose_data::add(int key, std::string& value) { return add(key, (unsigned char*)value.c_str(), value.size()); } + +cose_data& cose_data::add(int key, const std::string& value) { return add(key, (unsigned char*)value.c_str(), value.size()); } + +cose_data& cose_data::add(int key, binary_t& value) { return add(key, &value[0], value.size()); } + +cose_data& cose_data::add(int key, const binary_t& value) { return add(key, &value[0], value.size()); } + +cose_data& cose_data::replace(int key, const binary_t& value) { return replace(key, &value[0], value.size()); } + +cose_data& cose_data::add(int key, uint16 curve, const binary_t& x, const binary_t& y) { + cose_key* k = nullptr; + return_t ret = errorcode_t::success; + __try2 { + __try_new_catch(k, new cose_key(), ret, __leave2); + + k->set(&get_owner()->get_static_key(), curve, x, y); + add(key, TYPE_STATIC_KEY, k); + + _keys.push_back(k); + } + __finally2 { + // do nothing + } + return *this; +} + +cose_data& cose_data::add(int key, uint16 curve, const binary_t& x, const binary_t& y, std::list& order) { + cose_key* k = nullptr; + return_t ret = errorcode_t::success; + __try2 { + __try_new_catch(k, new cose_key(), ret, __leave2); + + k->set(&get_owner()->get_static_key(), curve, x, y); + k->set(order); + add(key, TYPE_STATIC_KEY, k); + + _keys.push_back(k); + } + __finally2 { + // do nothing + } + return *this; +} + +cose_data& cose_data::add(int key, uint16 curve, const binary_t& x, bool ysign) { + cose_key* k = nullptr; + return_t ret = errorcode_t::success; + __try2 { + __try_new_catch(k, new cose_key(), ret, __leave2); + + k->set(&get_owner()->get_static_key(), curve, x, ysign); + add(key, TYPE_STATIC_KEY, k); + + _keys.push_back(k); + } + __finally2 { + // do nothing + } + return *this; +} + +cose_data& cose_data::add(int key, uint16 curve, const binary_t& x, bool ysign, std::list& order) { + cose_key* k = nullptr; + return_t ret = errorcode_t::success; + __try2 { + __try_new_catch(k, new cose_key(), ret, __leave2); + + k->set(&get_owner()->get_static_key(), curve, x, ysign); + k->set(order); + add(key, TYPE_STATIC_KEY, k); + + _keys.push_back(k); + } + __finally2 { + // do nothing + } + return *this; +} + +cose_data& cose_data::add(cose_alg_t alg, const char* kid, const binary_t& signature) { + cose_countersign* countersign = nullptr; + return_t ret = errorcode_t::success; + + __try2 { + __try_new_catch(countersign, new cose_countersign, ret, __leave2); + countersign->set_upperlayer(get_owner()); + countersign->set_property(cose_property_t::cose_property_countersign); + + countersign->get_protected().add(cose_key_t::cose_alg, alg); + if (kid) { + countersign->get_unprotected().add(cose_key_t::cose_kid, kid); + } + countersign->get_signature().set(signature); + + add(countersign); + } + __finally2 { + // do nothing + } + return *this; +} + +cose_data& cose_data::add(cose_recipient* countersign) { + return_t ret = errorcode_t::success; + + __try2 { + cose_countersigns* countersigns = get_owner()->get_countersigns1(); + cose_variantmap_t::iterator iter = _data_map.find(cose_key_t::cose_counter_sig); + if (_data_map.end() == iter) { + add(cose_key_t::cose_counter_sig, TYPE_COUNTER_SIG, countersigns); + } + countersigns->add(countersign); + } + __finally2 { + // do nothing + } + return *this; +} + +cose_data& cose_data::add(int key, vartype_t vty, void* p) { + if (p) { + variant vt; + _data_map.insert(std::make_pair(key, std::move(vt.set_user_type(vty, p)))); + _order.push_back(key); + } + return *this; +} + +cose_data& cose_data::add(int key, variant& value) { + _data_map.insert(std::make_pair(key, value)); + _order.push_back(key); + return *this; +} + +cose_data& cose_data::set(const binary_t& bin) { + _payload = bin; + return *this; +} + +cose_data& cose_data::set(const std::string& value) { + _payload = convert(value); + return *this; +} + +cose_data& cose_data::set_b16(std::string const value) { + _payload = base16_decode(value); + return *this; +} + +cose_data& cose_data::set_b16(const char* value) { + if (value) { + _payload = base16_decode(value, strlen(value)); + } + return *this; +} + +cose_data& cose_data::clear() { + _data_map.clear(); + _order.clear(); + _payload.clear(); + for (std::list::iterator it = _keys.begin(); it != _keys.end(); it++) { + cose_key* object = *it; + delete object; + } + _keys.clear(); + return *this; +} + +bool cose_data::exist(int key) { + bool ret_value = false; + return_t ret = errorcode_t::success; + + std::map::iterator iter = _data_map.find(key); + if (_data_map.end() != iter) { + ret_value = true; + } + return ret_value; +} + +return_t cose_data::finditem(int key, int& value) { + return_t ret = errorcode_t::success; + + std::map::iterator iter = _data_map.find(key); + if (_data_map.end() == iter) { + ret = errorcode_t::not_found; + } else { + value = iter->second.to_int(); + } + return ret; +} + +return_t cose_data::finditem(int key, std::string& value) { + return_t ret = errorcode_t::success; + + std::map::iterator iter = _data_map.find(key); + if (_data_map.end() == iter) { + ret = errorcode_t::not_found; + } else { + iter->second.to_string(value); + } + return ret; +} + +return_t cose_data::finditem(int key, binary_t& value) { + return_t ret = errorcode_t::success; + variant vt; + + std::map::iterator iter = _data_map.find(key); + if (_data_map.end() == iter) { + ret = errorcode_t::not_found; + } else { + iter->second.to_binary(value); + } + return ret; +} + +return_t cose_data::build_protected(cbor_data** object) { + return_t ret = errorcode_t::success; + cbor_map* part_protected = nullptr; + + __try2 { + if (nullptr == object) { + ret = errorcode_t::invalid_parameter; + __leave2; + } + + if (_payload.size()) { + *object = new cbor_data(_payload); + } else { + if (_data_map.size()) { + __try_new_catch(part_protected, new cbor_map(), ret, __leave2); + + cose_orderlist_t::iterator list_iter; + for (list_iter = _order.begin(); list_iter != _order.end(); list_iter++) { + int key = *list_iter; + + cose_variantmap_t::iterator map_iter = _data_map.find(key); + variant value = map_iter->second; + *part_protected << new cbor_pair(new cbor_data(key), new cbor_data(std::move(value))); + } + + cbor_publisher publisher; + publisher.publish(part_protected, &_payload); + + *object = new cbor_data(_payload); + } else { + *object = new cbor_data(binary_t()); + } + } + } + __finally2 { + if (part_protected) { + part_protected->release(); + } + } + return ret; +} + +return_t cose_data::build_protected(cbor_data** object, cose_variantmap_t& unsent) { + return_t ret = errorcode_t::success; + cbor_map* part_protected = nullptr; + + __try2 { + if (nullptr == object) { + ret = errorcode_t::invalid_parameter; + __leave2; + } + + if (_payload.size()) { + *object = new cbor_data(_payload); + } else { + if (_data_map.size()) { + __try_new_catch(part_protected, new cbor_map(), ret, __leave2); + + cose_orderlist_t::iterator list_iter; + for (list_iter = _order.begin(); list_iter != _order.end(); list_iter++) { + int key = *list_iter; + + cose_variantmap_t::iterator unsent_iter = unsent.find(key); + if (unsent.end() != unsent_iter) { + continue; + } + + cose_variantmap_t::iterator map_iter = _data_map.find(key); + variant value = map_iter->second; + *part_protected << new cbor_pair(new cbor_data(key), new cbor_data(std::move(value))); + } + + cbor_publisher publisher; + publisher.publish(part_protected, &_payload); + + *object = new cbor_data(_payload); + } else { + *object = new cbor_data(binary_t()); + } + } + } + __finally2 { + if (part_protected) { + part_protected->release(); + } + } + return ret; +} + +return_t cose_data::build_unprotected(cbor_map** object) { + return_t ret = errorcode_t::success; + cbor_map* part_unprotected = nullptr; + + __try2 { + if (nullptr == object) { + ret = errorcode_t::invalid_parameter; + __leave2; + } + + __try_new_catch(part_unprotected, new cbor_map(), ret, __leave2); + + cose_orderlist_t::iterator list_iter; + for (list_iter = _order.begin(); list_iter != _order.end(); list_iter++) { + int key = *list_iter; + + cose_variantmap_t::iterator map_iter = _data_map.find(key); + variant value = map_iter->second; + variant_t& vt = value.content(); + + if (TYPE_STATIC_KEY == vt.type) { + cose_key* k = (cose_key*)vt.data.p; + *part_unprotected << new cbor_pair(key, k->cbor()); + } else if (TYPE_COUNTER_SIG == vt.type) { + cose_countersigns* signs = get_owner()->get_countersigns1(); + *part_unprotected << new cbor_pair(cose_key_t::cose_counter_sig, signs->cbor()); + } else { + *part_unprotected << new cbor_pair(new cbor_data(key), new cbor_data(value)); + } + } + + *object = part_unprotected; + } + __finally2 { + // do nothing + } + return ret; +} + +return_t cose_data::build_unprotected(cbor_map** object, cose_variantmap_t& unsent) { + return_t ret = errorcode_t::success; + cbor_map* part_unprotected = nullptr; + + __try2 { + if (nullptr == object) { + ret = errorcode_t::invalid_parameter; + __leave2; + } + + __try_new_catch(part_unprotected, new cbor_map(), ret, __leave2); + + cose_orderlist_t::iterator list_iter; + for (list_iter = _order.begin(); list_iter != _order.end(); list_iter++) { + int key = *list_iter; + + cose_variantmap_t::iterator unsent_iter = unsent.find(key); + if (unsent.end() != unsent_iter) { + continue; + } + + cose_variantmap_t::iterator map_iter = _data_map.find(key); + variant value = map_iter->second; + variant_t& vt = value.content(); + + if (TYPE_STATIC_KEY == vt.type) { + cose_key* k = (cose_key*)vt.data.p; + *part_unprotected << new cbor_pair(key, k->cbor()); + } else if (TYPE_COUNTER_SIG == vt.type) { + cose_recipient* sign = (cose_recipient*)vt.data.p; + *part_unprotected << new cbor_pair(cose_key_t::cose_counter_sig, sign->cbor()); + } else { + *part_unprotected << new cbor_pair(new cbor_data(key), new cbor_data(value)); + } + } + + *object = part_unprotected; + } + __finally2 { + // do nothing + } + return ret; +} + +return_t cose_data::build_data(cbor_data** object) { + return_t ret = errorcode_t::success; + + __try2 { + if (nullptr == object) { + ret = errorcode_t::invalid_parameter; + __leave2; + } + + __try_new_catch(*object, new cbor_data(_payload), ret, __leave2); + } + __finally2 { + // do nothing + } + return ret; +} + +return_t cose_data::parse_protected(cbor_data* object) { + return_t ret = errorcode_t::success; + cbor_object* root = nullptr; + + __try2 { + if (nullptr == object) { + ret = errorcode_t::invalid_parameter; + __leave2; + } + + object->data().to_binary(_payload); + + if (0 == _payload.size()) { + __leave2; + } + + ret = cbor_parse(&root, _payload); + if (errorcode_t::success != ret) { + __leave2; + } + cbor_map* datamap = cbor_typeof(root, cbor_type_t::cbor_type_map); + if (nullptr == datamap) { + ret = errorcode_t::bad_format; + __leave2; + } + + ret = parse(datamap); + } + __finally2 { + if (root) { + root->release(); + } + } + return ret; +} + +return_t cose_data::parse_unprotected(cbor_map* object) { + return_t ret = errorcode_t::success; + + __try2 { + if (nullptr == object) { + ret = errorcode_t::invalid_parameter; + __leave2; + } + + ret = parse(object); + } + __finally2 { + // do nothing + } + return ret; +} + +return_t cose_data::parse_payload(cbor_data* object) { + return_t ret = errorcode_t::success; + + __try2 { + if (nullptr == object) { + ret = errorcode_t::invalid_parameter; + __leave2; + } + + object->data().to_binary(_payload); + } + __finally2 { + // do nothing + } + return ret; +} + +return_t cose_data::parse(cbor_map* object) { + return_t ret = errorcode_t::success; + return_t check = errorcode_t::success; + + __try2 { + if (nullptr == object) { + ret = errorcode_t::invalid_parameter; + __leave2; + } + + size_t size_map = object->size(); + for (size_t i = 0; i < size_map; i++) { + cbor_pair* pair = (*object)[i]; + + cbor_data* pair_key = pair->left(); + int keyid = 0; + keyid = pair_key->data().to_int(); + + cbor_object* pair_value = pair->right(); + + cbor_data* data = cbor_typeof(pair_value, cbor_type_t::cbor_type_data); + if (data) { + add(keyid, data->data()); + continue; + } + + cbor_simple* simple = cbor_typeof(pair_value, cbor_type_t::cbor_type_simple); + if (simple) { + cbor_simple_t simple_type = simple->simple_type(); + switch (simple_type) { + case cbor_simple_true: + add_bool(keyid, true); + break; + case cbor_simple_false: + add_bool(keyid, false); + break; + default: + break; + } + continue; + } + + cbor_map* map = cbor_typeof(pair_value, cbor_type_t::cbor_type_map); + if (map) { + parse_static_key(map, keyid); + continue; + } + + cbor_array* array = cbor_typeof(pair_value, cbor_type_t::cbor_type_array); + if (array) { + switch (keyid) { + case cose_counter_sig: // (7) + { + cbor_data* countersig_protected = cbor_typeof((*array)[0], cbor_type_t::cbor_type_data); + if (countersig_protected) { + parse_counter_signs(array, keyid); + } else { + cbor_array* countersigns = cbor_typeof((*array)[0], cbor_type_t::cbor_type_array); + if (countersigns) { + for (size_t size = 0; size < countersigns->size(); size++) { + cbor_array* countersign = cbor_typeof((*array)[size], cbor_type_t::cbor_type_array); + parse_counter_signs(countersign, keyid); + } + } + } + } break; + case cose_crit: // (2) + default: + break; + } + continue; + } + } + } + __finally2 { + // do nothing + } + return ret; +} + +return_t cose_data::parse_static_key(cbor_map* object, int keyid) { + return_t ret = errorcode_t::success; + return_t check = errorcode_t::success; + + __try2 { + if (nullptr == object) { + ret = errorcode_t::invalid_parameter; + __leave2; + } + + cbor_map_hint> hint(object); + cose_orderlist_t order; + uint16 kty = 0; + uint16 curve = 0; + binary_t bin_x; + binary_t bin_y; + + cbor_object* cbor_curve = nullptr; + cbor_object* cbor_x = nullptr; + cbor_object* cbor_y = nullptr; + + hint.find(cose_key_lable_t::cose_ec_crv, &cbor_curve); + hint.find(cose_key_lable_t::cose_ec_x, &cbor_x); + hint.find(cose_key_lable_t::cose_ec_y, &cbor_y); + hint.get_order(order); + + if (cbor_curve && cbor_x) { + cbor_data* cbor_data_curve = cbor_typeof(cbor_curve, cbor_type_t::cbor_type_data); + cbor_data* cbor_data_x = cbor_typeof(cbor_x, cbor_type_t::cbor_type_data); + cbor_data* cbor_data_y = cbor_typeof(cbor_y, cbor_type_t::cbor_type_data); + cbor_simple* cbor_simple_y = cbor_typeof(cbor_y, cbor_type_t::cbor_type_simple); + + curve = cbor_data_curve->data().to_int(); + cbor_data_x->data().to_binary(bin_x); + + switch (curve) { + case cose_ec_p256: + case cose_ec_p384: + case cose_ec_p521: + if (cbor_data_y) { + cbor_data_y->data().to_binary(bin_y); + add(keyid, curve, bin_x, bin_y, order); + } else if (cbor_simple_y) { + add(keyid, curve, bin_x, cbor_simple_true == cbor_simple_y->simple_type(), order); + } else { + ret = errorcode_t::bad_format; + } + break; + case cose_ec_x25519: + case cose_ec_x448: + case cose_ec_ed25519: + case cose_ec_ed448: + add(keyid, curve, bin_x, bin_y, order); + break; + } + + cbor_curve->release(); + cbor_x->release(); + } + + if (cbor_y) { + cbor_y->release(); + } + } + __finally2 { + // do nothing + } + return ret; +} + +return_t cose_data::parse_counter_signs(cbor_array* object, int keyid) { + return_t ret = errorcode_t::success; + __try2 { + if (nullptr == object) { + ret = errorcode_t::invalid_parameter; + __leave2; + } + + if (object->size() == 3) { + cbor_data* countersig_protected = cbor_typeof((*object)[0], cbor_type_t::cbor_type_data); + cbor_map* countersig_unprotected = cbor_typeof((*object)[1], cbor_type_t::cbor_type_map); + cbor_data* countersig_signature = cbor_typeof((*object)[2], cbor_type_t::cbor_type_data); + if (countersig_protected && countersig_unprotected && countersig_signature) { + cose_countersign* countersign = nullptr; + __try_new_catch_only(countersign, new cose_countersign); + + countersign->set_upperlayer(get_owner()); + countersign->set_composer(get_owner()->get_composer()); + countersign->set_property(cose_property_t::cose_property_countersign); + + countersign->get_protected().set(countersig_protected); + countersign->get_unprotected().set(countersig_unprotected); // keep order + countersign->get_signature().set(countersig_signature); + + add(countersign); + } + } + } + __finally2 { + // do nothing + } + return ret; +} + +bool cose_data::empty_binary() { return 0 == _payload.size(); } + +size_t cose_data::size_binary() { return _payload.size(); } + +void cose_data::get_binary(binary_t& bin) { bin = _payload; } + +} // namespace crypto +} // namespace hotplace diff --git a/sdk/crypto/cose/cose_key.cpp b/sdk/crypto/cose/cose_key.cpp new file mode 100644 index 0000000..237d0ae --- /dev/null +++ b/sdk/crypto/cose/cose_key.cpp @@ -0,0 +1,120 @@ +/* vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab smarttab : */ +/** + * @file {file} + * @author Soo Han, Kim (princeb612.kr@gmail.com) + * @desc + * + * Revision History + * Date Name Description + * + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace hotplace { +using namespace io; +namespace crypto { + +cose_data::cose_key::cose_key() : _curve(0) {} + +void cose_data::cose_key::set(crypto_key* key, uint16 curve, const binary_t& x, const binary_t& y) { + _curve = curve; + _x = x; + _y = y; + _compressed = false; + + crypto_advisor* advisor = crypto_advisor::get_instance(); + const hint_curve_t* hint = advisor->hintof_curve((cose_ec_curve_t)curve); + crypto_keychain keychain; + binary_t d; + keychain.add_ec(key, nullptr, hint->nid, x, y, d); +} + +void cose_data::cose_key::set(crypto_key* key, uint16 curve, const binary_t& x, bool ysign) { + _curve = curve; + _x = x; + _y.clear(); + _ysign = ysign; + _compressed = true; + + crypto_advisor* advisor = crypto_advisor::get_instance(); + const hint_curve_t* hint = advisor->hintof_curve((cose_ec_curve_t)curve); + crypto_keychain keychain; + binary_t d; + keychain.add_ec(key, nullptr, hint->nid, x, ysign, d); +} + +void cose_data::cose_key::set(cose_orderlist_t& order) { _order = order; } + +cbor_map* cose_data::cose_key::cbor() { + cbor_map* object = nullptr; + __try2 { + __try_new_catch_only(object, new cbor_map()); + if (nullptr == object) { + __leave2; + } + + cose_kty_t kty; + switch (_curve) { + case cose_ec_p256: + case cose_ec_p384: + case cose_ec_p521: + kty = cose_kty_t::cose_kty_ec2; + break; + default: + kty = cose_kty_t::cose_kty_okp; + break; + } + + if (_order.size()) { + for (cose_orderlist_t::iterator iter = _order.begin(); iter != _order.end(); iter++) { + int key = *iter; + switch (key) { + case cose_key_lable_t::cose_lable_kty: + *object << new cbor_pair(cose_key_lable_t::cose_lable_kty, new cbor_data(kty)); + break; + case cose_key_lable_t::cose_ec_crv: + *object << new cbor_pair(cose_key_lable_t::cose_ec_crv, new cbor_data(_curve)); + break; + case cose_key_lable_t::cose_ec_x: + *object << new cbor_pair(cose_key_lable_t::cose_ec_x, new cbor_data(_x)); + break; + case cose_key_lable_t::cose_ec_y: + if (_compressed) { + *object << new cbor_pair(cose_key_lable_t::cose_ec_y, new cbor_data(_ysign)); // y(-3) + } else { + *object << new cbor_pair(cose_key_lable_t::cose_ec_y, new cbor_data(_y)); // y(-3) + } + break; + default: + break; + } + } + } else { + *object << new cbor_pair(cose_key_lable_t::cose_lable_kty, new cbor_data(kty)) // kty(1) + << new cbor_pair(cose_key_lable_t::cose_ec_crv, new cbor_data(_curve)) // crv(-1) + << new cbor_pair(cose_key_lable_t::cose_ec_x, new cbor_data(_x)); // x(-2) + + if (cose_kty_t::cose_kty_ec2 == kty) { + if (_compressed) { + *object << new cbor_pair(cose_key_lable_t::cose_ec_y, new cbor_data(_ysign)); // y(-3) + } else { + *object << new cbor_pair(cose_key_lable_t::cose_ec_y, new cbor_data(_y)); // y(-3) + } + } + } + } + __finally2 { + // do nothing + } + return object; +} + +} // namespace crypto +} // namespace hotplace diff --git a/sdk/crypto/cose/cose_protected.cpp b/sdk/crypto/cose/cose_protected.cpp new file mode 100644 index 0000000..3b9e237 --- /dev/null +++ b/sdk/crypto/cose/cose_protected.cpp @@ -0,0 +1,63 @@ +/* vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab smarttab : */ +/** + * @file {file} + * @author Soo Han, Kim (princeb612.kr@gmail.com) + * @desc + * + * Revision History + * Date Name Description + * + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace hotplace { +using namespace io; +namespace crypto { + +cose_protected::cose_protected() {} + +cose_protected::~cose_protected() {} + +cose_protected& cose_protected::add(cose_key_t key, uint32 value) { + _protected.add(key, value); + return *this; +} + +cose_protected& cose_protected::set(const binary_t& bin) { + _protected.set(bin); + cbor_object* root = nullptr; + cbor_parse(&root, bin); + if (root) { + cbor_data* object = cbor_typeof(root, cbor_type_t::cbor_type_data); + if (object) { + set(object); + } + root->release(); + } + return *this; +} + +return_t cose_protected::set(cbor_data* object) { return _protected.parse_protected(object); } + +cose_data& cose_protected::data() { return _protected; } + +cose_protected& cose_protected::clear() { + _protected.clear(); + return *this; +} + +cbor_data* cose_protected::cbor() { + cbor_data* object = nullptr; + _protected.build_protected(&object); + return object; +} + +} // namespace crypto +} // namespace hotplace diff --git a/sdk/crypto/cose/cose_recipient.cpp b/sdk/crypto/cose/cose_recipient.cpp new file mode 100644 index 0000000..578fcd7 --- /dev/null +++ b/sdk/crypto/cose/cose_recipient.cpp @@ -0,0 +1,512 @@ +/* vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab smarttab : */ +/** + * @file {file} + * @author Soo Han, Kim (princeb612.kr@gmail.com) + * @desc + * + * Revision History + * Date Name Description + * + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace hotplace { +using namespace io; +namespace crypto { + +cose_recipient::cose_recipient() + : _upperlayer(nullptr), + _depth(0), + _property(cose_property_t::cose_property_normal), + _composer(nullptr), + _cbor_tag(cbor_tag_t::cbor_tag_unknown), + _countersigns(nullptr) { + get_protected().data().set_owner(this); + get_unprotected().data().set_owner(this); + get_payload().data().set_owner(this); + get_singleitem().data().set_owner(this); + get_recipients().set_upperlayer(this); +} + +cose_recipient::~cose_recipient() { + if (_countersigns) { + delete _countersigns; + } +} + +void cose_recipient::set_upperlayer(cose_recipient* layer) { + _upperlayer = layer; + set_composer(layer->get_composer()); + + if (layer) { + _depth = layer->get_depth() + 1; + } +} + +cose_recipient* cose_recipient::get_upperlayer() { return _upperlayer; } + +cose_recipient* cose_recipient::get_upperlayer2() { + cose_recipient* layer = nullptr; + if (_upperlayer) { + layer = _upperlayer; + } else { + layer = this; // aka body, composer.get_layer() + } + return layer; +} + +uint16 cose_recipient::get_depth() { return _depth; } + +void cose_recipient::set_composer(cose_composer* composer) { _composer = composer; } + +cose_composer* cose_recipient::get_composer() { return _composer; } + +cose_recipient& cose_recipient::set_property(uint16 property) { + _property = property; + return *this; +} + +uint16 cose_recipient::get_property() { return _property; } + +cose_recipient& cose_recipient::add(cose_recipient* recipient) { + cose_recipient* object = recipient; + if (nullptr == object) { + object = new cose_recipient; + } + + object->set_upperlayer(this); + object->set_composer(get_composer()); + + return _recipients.add(object); +} + +return_t cose_recipient::finditem(int key, int& value, int scope) { + return_t ret = errorcode_t::not_found; + __try2 { + if (cose_scope::cose_scope_unsent & scope) { + ret = get_composer()->get_unsent().data().finditem(key, value); + if (errorcode_t::success == ret) { + __leave2; + } + } + if (cose_scope::cose_scope_protected & scope) { + ret = get_protected().data().finditem(key, value); + if (errorcode_t::success == ret) { + __leave2; + } + } + if (cose_scope::cose_scope_unprotected & scope) { + ret = get_unprotected().data().finditem(key, value); + if (errorcode_t::success == ret) { + __leave2; + } + } + if (cose_scope::cose_scope_children & scope) { + ret = get_recipients().finditem(key, value, scope); + } + } + __finally2 { + // do nothing + } + return ret; +} + +return_t cose_recipient::finditem(int key, std::string& value, int scope) { + return_t ret = errorcode_t::not_found; + __try2 { + if (cose_scope::cose_scope_unsent & scope) { + ret = get_composer()->get_unsent().data().finditem(key, value); + if (errorcode_t::success == ret) { + __leave2; + } + } + if (cose_scope::cose_scope_protected & scope) { + ret = get_protected().data().finditem(key, value); + if (errorcode_t::success == ret) { + __leave2; + } + } + if (cose_scope::cose_scope_unprotected & scope) { + ret = get_unprotected().data().finditem(key, value); + if (errorcode_t::success == ret) { + __leave2; + } + } + if (cose_scope::cose_scope_children & scope) { + ret = get_recipients().finditem(key, value, scope); + if (errorcode_t::success == ret) { + __leave2; + } + } + } + __finally2 { + // do nothing + } + return ret; +} + +return_t cose_recipient::finditem(int key, binary_t& value, int scope) { + return_t ret = errorcode_t::not_found; + __try2 { + if (cose_scope::cose_scope_unsent & scope) { + ret = get_composer()->get_unsent().data().finditem(key, value); + if (errorcode_t::success == ret) { + __leave2; + } + } + if (cose_scope::cose_scope_params & scope) { + ret = get_params().finditem(key, value); + if (errorcode_t::success == ret) { + __leave2; + } + } + if (cose_scope::cose_scope_protected & scope) { + ret = get_protected().data().finditem(key, value); + if (errorcode_t::success == ret) { + __leave2; + } + } + if (cose_scope::cose_scope_unprotected & scope) { + ret = get_unprotected().data().finditem(key, value); + if (errorcode_t::success == ret) { + __leave2; + } + } + if (cose_scope::cose_scope_children & scope) { + ret = get_recipients().finditem(key, value, scope); + } + } + __finally2 { + // do nothing + } + return ret; +} + +return_t cose_recipient::setparam(cose_param_t id, const binary_t& bin) { + return_t ret = errorcode_t::success; + __try2 { + switch (id) { + case cose_param_t::cose_param_cek: + case cose_param_t::cose_param_ciphertext: + case cose_param_t::cose_param_secret: + case cose_param_t::cose_param_plaintext: + get_params().replace(id, bin); + break; + default: + ret = errorcode_t::request; + break; + } + } + __finally2 { + // do nothing + } + return ret; +} + +return_t cose_recipient::getparam(cose_param_t id, binary_t& bin) { + return_t ret = errorcode_t::success; + __try2 { + switch (id) { + case cose_param_t::cose_param_cek: + case cose_param_t::cose_param_ciphertext: + case cose_param_t::cose_param_secret: + case cose_param_t::cose_param_plaintext: + get_params().replace(id, bin); + break; + default: + ret = errorcode_t::request; + break; + } + } + __finally2 { + // do nothing + } + return ret; +} + +return_t cose_recipient::parse(cbor_array* root) { + return_t ret = errorcode_t::success; + crypto_advisor* advisor = crypto_advisor::get_instance(); + cbor_tag_t cbor_tag = cbor_tag_t::cbor_tag_unknown; + + __try2 { + clear(); + + if (nullptr == root) { + ret = errorcode_t::invalid_parameter; + __leave2; + } + + ret = parse_header(root); + if (errorcode_t::success != ret) { + __leave2; + } + + ret = parse_message(root); + if (errorcode_t::success != ret) { + __leave2; + } + } + __finally2 { + // do nothing + if (errorcode_t::success != ret) { + // throw; + } + } + return ret; +} + +return_t cose_recipient::parse_header(cbor_array* root) { + return_t ret = errorcode_t::success; + + __try2 { + if (nullptr == root) { + ret = errorcode_t::invalid_parameter; + __leave2; + } + + size_t size_message = root->size(); + + if (size_message < 3) { + ret = errorcode_t::bad_format; + __leave2; + } + + // parse protected and unprotected + ret = parse_protected((*root)[0]); + if (errorcode_t::success != ret) { + __leave2; + } + + ret = parse_unprotected((*root)[1]); + if (errorcode_t::success != ret) { + __leave2; + } + + ret = parse_payload((*root)[2]); + if (errorcode_t::success != ret) { + __leave2; + } + } + __finally2 { + // do nothing + } + return ret; +} + +return_t cose_recipient::parse_message(cbor_array* root) { + return_t ret = errorcode_t::success; + crypto_advisor* advisor = crypto_advisor::get_instance(); + size_t i = 0; + + __try2 { + if (nullptr == root) { + ret = errorcode_t::invalid_parameter; + __leave2; + } + + size_t size_message = root->size(); + for (i = 3; i < size_message; i++) { + cbor_object* cbor_item = (*root)[i]; + + // in case of cose_tag_mac/cose_tag_mac0 + cbor_data* cbor_singleitem = cbor_typeof(cbor_item, cbor_type_t::cbor_type_data); + if (cbor_singleitem) { + parse_singleitem(cbor_item); + continue; + } + + // in case of cose_tag_encrypt/cose_tag_mac/cose_tag_sign + cbor_array* cbor_recipients = cbor_typeof(cbor_item, cbor_type_t::cbor_type_array); + if (cbor_recipients) { + for (size_t size = 0; size < cbor_recipients->size(); size++) { + cbor_array* cbor_recipient = cbor_typeof((*cbor_recipients)[size], cbor_type_t::cbor_type_array); + if (cbor_recipient) { + add().parse(cbor_recipient); + } + } + continue; + } + } + } + __finally2 { + // do nothing + } + return ret; +} + +return_t cose_recipient::parse_protected(cbor_object* object) { + return_t ret = errorcode_t::success; + + __try2 { + if (nullptr == object) { + ret = errorcode_t::invalid_parameter; + __leave2; + } + + cbor_data* cbor_protected = cbor_typeof(object, cbor_type_t::cbor_type_data); + if (nullptr == cbor_protected) { + ret = errorcode_t::bad_format; + __leave2; + } + + ret = get_protected().set(cbor_protected); + } + __finally2 { + // do nothing + } + return ret; +} + +return_t cose_recipient::parse_unprotected(cbor_object* object) { + return_t ret = errorcode_t::success; + __try2 { + if (nullptr == object) { + ret = errorcode_t::invalid_parameter; + __leave2; + } + + cbor_map* cbor_unprotected = cbor_typeof(object, cbor_type_t::cbor_type_map); + if (nullptr == cbor_unprotected) { + ret = errorcode_t::bad_format; + __leave2; + } + + ret = get_unprotected().set(cbor_unprotected); + } + __finally2 { + // do nothing + } + return ret; +} + +return_t cose_recipient::parse_payload(cbor_object* object) { + return_t ret = errorcode_t::success; + + __try2 { + if (nullptr == object) { + ret = errorcode_t::invalid_parameter; + __leave2; + } + + cbor_data* cbor_payload = cbor_typeof(object, cbor_type_t::cbor_type_data); + if (nullptr == cbor_payload) { + ret = errorcode_t::bad_format; + __leave2; + } + + ret = get_payload().set(cbor_payload); + } + __finally2 { + // do nothing + } + return ret; +} + +return_t cose_recipient::parse_singleitem(cbor_object* object) { + return_t ret = errorcode_t::success; + + __try2 { + if (nullptr == object) { + ret = errorcode_t::invalid_parameter; + __leave2; + } + + cbor_data* cbor_singleitem = cbor_typeof(object, cbor_type_t::cbor_type_data); + if (nullptr == cbor_singleitem) { + ret = errorcode_t::bad_format; + __leave2; + } + + ret = get_singleitem().set(cbor_singleitem); + } + __finally2 { + // do nothing + } + return ret; +} + +cose_protected& cose_recipient::get_protected() { return _protected; } + +cose_unprotected& cose_recipient::get_unprotected() { return _unprotected; } + +cose_binary& cose_recipient::get_payload() { return _payload; } + +cose_binary& cose_recipient::get_singleitem() { return _singleitem; } + +cose_binary& cose_recipient::get_signature() { return _singleitem; } + +cose_binary& cose_recipient::get_tag() { return _singleitem; } + +cose_recipients& cose_recipient::get_recipients() { return _recipients; } + +cose_data& cose_recipient::get_params() { return _params; } + +crypto_key& cose_recipient::get_static_key() { return _static_key; } + +cose_countersigns* cose_recipient::get_countersigns0() { return _countersigns; } + +cose_countersigns* cose_recipient::get_countersigns1() { + if (nullptr == _countersigns) { + _countersigns = new cose_countersigns; + _countersigns->set_upperlayer(this); + } + return _countersigns; +} + +cose_recipient& cose_recipient::clear() { + _cbor_tag = cbor_tag_t::cbor_tag_unknown; + get_protected().clear(); + get_unprotected().clear(); + get_payload().clear(); + get_singleitem().clear(); + get_recipients().clear(); + if (_countersigns) { + delete _countersigns; + _countersigns = nullptr; + } + get_static_key().clear(); + get_params().clear(); + return *this; +} + +cose_alg_t cose_recipient::get_algorithm() { + int alg = cose_alg_t::cose_unknown; + get_protected().data().finditem(cose_key_t::cose_alg, alg); + if (cose_alg_t::cose_unknown == alg) { + get_unprotected().data().finditem(cose_key_t::cose_alg, alg); + } + return (cose_alg_t)alg; +} + +std::string cose_recipient::get_kid() { + std::string kid; + get_unprotected().data().finditem(cose_key_t::cose_kid, kid); + return kid; +} + +void cose_recipient::for_each(void (*for_each_handler)(cose_layer*, void* userdata), void* userdata) { + if (for_each_handler) { + for_each_handler(this, userdata); + _recipients.for_each(for_each_handler, userdata); + } +} + +cbor_array* cose_recipient::cbor() { + cbor_array* object = new cbor_array; + *object << get_protected().cbor() << get_unprotected().cbor() << get_payload().cbor(); + if (_recipients.size()) { + *object << _recipients.cbor(); + } + return object; +} + +} // namespace crypto +} // namespace hotplace diff --git a/sdk/crypto/cose/cose_recipients.cpp b/sdk/crypto/cose/cose_recipients.cpp new file mode 100644 index 0000000..195724b --- /dev/null +++ b/sdk/crypto/cose/cose_recipients.cpp @@ -0,0 +1,124 @@ +/* vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab smarttab : */ +/** + * @file {file} + * @author Soo Han, Kim (princeb612.kr@gmail.com) + * @desc + * + * Revision History + * Date Name Description + * + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace hotplace { +using namespace io; +namespace crypto { + +cose_recipients::cose_recipients() : _upperlayer(nullptr) {} + +cose_recipients::~cose_recipients() { clear(); } + +cose_recipient& cose_recipients::add(cose_recipient* recipient) { + recipient->set_upperlayer(get_upperlayer()); + std::list::iterator iter = _recipients.insert(_recipients.end(), recipient); + return **iter; +} + +cose_recipients& cose_recipients::clear() { + for (std::list::iterator iter = _recipients.begin(); iter != _recipients.end(); iter++) { + cose_recipient* item = *iter; + delete item; + } + _recipients.clear(); + return *this; +} + +bool cose_recipients::empty() { return (0 == _recipients.size()); } + +size_t cose_recipients::size() { return _recipients.size(); } + +cose_recipient* cose_recipients::operator[](size_t index) { + cose_recipient* object = nullptr; + if (index < _recipients.size()) { + std::list::iterator iter = _recipients.begin(); + std::advance(iter, index); + object = *iter; + } + return object; +} + +void cose_recipients::for_each(void (*for_each_handler)(cose_layer*, void* userdata), void* userdata) { + if (for_each_handler) { + std::list::iterator iter; + for (iter = _recipients.begin(); iter != _recipients.end(); iter++) { + cose_recipient* item = *iter; + item->for_each(for_each_handler, userdata); + } + } +} + +cose_recipients& cose_recipients::set_upperlayer(cose_recipient* layer) { + _upperlayer = layer; + return *this; +} + +cose_recipient* cose_recipients::get_upperlayer() { return _upperlayer; } + +return_t cose_recipients::finditem(int key, int& value, int scope) { + return_t ret = errorcode_t::not_found; + std::list::iterator iter; + for (iter = _recipients.begin(); iter != _recipients.end(); iter++) { + cose_recipient* item = *iter; + ret = item->finditem(key, value, scope); + if (errorcode_t::success == ret) { + break; + } + } + return ret; +} + +return_t cose_recipients::finditem(int key, std::string& value, int scope) { + return_t ret = errorcode_t::not_found; + std::list::iterator iter; + for (iter = _recipients.begin(); iter != _recipients.end(); iter++) { + cose_recipient* item = *iter; + ret = item->finditem(key, value, scope); + if (errorcode_t::success == ret) { + break; + } + } + return ret; +} + +return_t cose_recipients::finditem(int key, binary_t& value, int scope) { + return_t ret = errorcode_t::not_found; + std::list::iterator iter; + for (iter = _recipients.begin(); iter != _recipients.end(); iter++) { + cose_recipient* item = *iter; + ret = item->finditem(key, value, scope); + if (errorcode_t::success == ret) { + break; + } + } + return ret; +} + +cbor_array* cose_recipients::cbor() { + cbor_array* object = new cbor_array; + std::list::iterator iter; + for (iter = _recipients.begin(); iter != _recipients.end(); iter++) { + cose_recipient* item = *iter; + *object << item->cbor(); + } + return object; +} + +} // namespace crypto +} // namespace hotplace diff --git a/sdk/crypto/cose/cose_unprotected.cpp b/sdk/crypto/cose/cose_unprotected.cpp new file mode 100644 index 0000000..c2fa318 --- /dev/null +++ b/sdk/crypto/cose/cose_unprotected.cpp @@ -0,0 +1,89 @@ +/* vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab smarttab : */ +/** + * @file {file} + * @author Soo Han, Kim (princeb612.kr@gmail.com) + * @desc + * + * Revision History + * Date Name Description + * + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace hotplace { +using namespace io; +namespace crypto { + +cose_unprotected::cose_unprotected() {} + +cose_unprotected::~cose_unprotected() {} + +cose_unprotected& cose_unprotected::add(cose_key_t key, int32 value) { + _unprotected.add(key, value); + return *this; +} + +cose_unprotected& cose_unprotected::add(cose_key_t key, const char* value) { + _unprotected.add(key, value); + return *this; +} + +cose_unprotected& cose_unprotected::add(cose_key_t key, std::string& value) { + _unprotected.add(key, value); + return *this; +} + +cose_unprotected& cose_unprotected::add(cose_key_t key, const std::string& value) { + _unprotected.add(key, value); + return *this; +} + +cose_unprotected& cose_unprotected::add(cose_key_t key, binary_t& value) { + _unprotected.add(key, value); + return *this; +} + +cose_unprotected& cose_unprotected::add(cose_key_t key, const binary_t& value) { + _unprotected.add(key, value); + return *this; +} + +cose_unprotected& cose_unprotected::add(cose_key_t key, uint16 curve, const binary_t& x, const binary_t& y) { + _unprotected.add(key, curve, x, y); + return *this; +} + +cose_unprotected& cose_unprotected::add(cose_key_t key, uint16 curve, const binary_t& x, bool ysign) { + _unprotected.add(key, curve, x, ysign); + return *this; +} + +cose_unprotected& cose_unprotected::add(cose_alg_t alg, const char* kid, const binary_t& signature) { + _unprotected.add(alg, kid, signature); + return *this; +} + +return_t cose_unprotected::set(cbor_map* object) { return _unprotected.parse_unprotected(object); } + +cose_data& cose_unprotected::data() { return _unprotected; } + +cose_unprotected& cose_unprotected::clear() { + _unprotected.clear(); + return *this; +} + +cbor_map* cose_unprotected::cbor() { + cbor_map* object = nullptr; + _unprotected.build_unprotected(&object); + return object; +} + +} // namespace crypto +} // namespace hotplace diff --git a/sdk/crypto/cose/cose_unsent.cpp b/sdk/crypto/cose/cose_unsent.cpp new file mode 100644 index 0000000..11897ed --- /dev/null +++ b/sdk/crypto/cose/cose_unsent.cpp @@ -0,0 +1,82 @@ +/* vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab smarttab : */ +/** + * @file {file} + * @author Soo Han, Kim (princeb612.kr@gmail.com) + * @desc + * + * Revision History + * Date Name Description + * + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace hotplace { +using namespace io; +namespace crypto { + +cose_unsent::cose_unsent() {} + +cose_unsent::~cose_unsent() {} + +cose_data& cose_unsent::data() { return _unsent; } + +bool cose_unsent::isvalid(int key) { + bool ret = true; + switch (key) { + case cose_param_t::cose_external: + case cose_param_t::cose_unsent_apu_id: + case cose_param_t::cose_unsent_apu_nonce: + case cose_param_t::cose_unsent_apu_other: + case cose_param_t::cose_unsent_apv_id: + case cose_param_t::cose_unsent_apv_nonce: + case cose_param_t::cose_unsent_apv_other: + case cose_param_t::cose_unsent_pub_other: + case cose_param_t::cose_unsent_priv_other: + case cose_param_t::cose_unsent_iv: + case cose_param_t::cose_unsent_alg: + case cose_param_t::cose_param_cek: + break; + default: + ret = false; + break; + } + return ret; +} + +cose_unsent& cose_unsent::add(int key, const char* value) { + if (value && isvalid(key)) { + _unsent.add(key, value); + } + return *this; +} + +cose_unsent& cose_unsent::add(int key, const unsigned char* value, size_t size) { + if (value && isvalid(key)) { + _unsent.add(key, value, size); + } + return *this; +} + +cose_unsent& cose_unsent::add(int key, binary_t& value) { + if (isvalid(key)) { + _unsent.add(key, value); + } + return *this; +} + +cose_unsent& cose_unsent::add(int key, const binary_t& value) { + if (isvalid(key)) { + _unsent.add(key, value); + } + return *this; +} + +} // namespace crypto +} // namespace hotplace diff --git a/sdk/net/server/network_stream.cpp b/sdk/net/server/network_stream.cpp index 0f5088e..84a4f78 100644 --- a/sdk/net/server/network_stream.cpp +++ b/sdk/net/server/network_stream.cpp @@ -9,6 +9,7 @@ */ #include +#include #include #include @@ -62,8 +63,8 @@ return_t network_stream::consume(network_stream_data** ptr_buffer_object) { *ptr_buffer_object = nullptr; network_stream_data* buffer_object = nullptr; - network_stream_data* first = nullptr; - network_stream_data* prev = nullptr; + + t_single_linkable single_link; critical_section_guard guard(_lock); @@ -71,20 +72,12 @@ return_t network_stream::consume(network_stream_data** ptr_buffer_object) { ret = errorcode_t::empty; } else { while (false == _queue.empty()) { - buffer_object = _queue.front(); - buffer_object->_next = nullptr; - if (nullptr == first) { - first = buffer_object; - } - if (nullptr != prev) { - prev->_next = buffer_object; - } - prev = buffer_object; + single_link.add(_queue.front()); _queue.pop_front(); } } - *ptr_buffer_object = first; + *ptr_buffer_object = single_link.get_head(); } return ret; @@ -310,6 +303,8 @@ byte_t* network_stream_data::content() { return _ptr; } network_stream_data* network_stream_data::next() { return _next; } +void network_stream_data::set_next(network_stream_data* next) { _next = next; } + int network_stream_data::get_priority() { return _priority; } void network_stream_data::set_priority(int priority) { _priority = priority; } diff --git a/sdk/net/server/network_stream.hpp b/sdk/net/server/network_stream.hpp index 6f06bf7..321ef0b 100644 --- a/sdk/net/server/network_stream.hpp +++ b/sdk/net/server/network_stream.hpp @@ -46,6 +46,7 @@ class network_stream_data { * @brief next node */ network_stream_data* next(); + void set_next(network_stream_data* next); int get_priority(); void set_priority(int priority); diff --git a/sdk/nostd.hpp b/sdk/nostd.hpp index adeb0fa..ca67b9a 100644 --- a/sdk/nostd.hpp +++ b/sdk/nostd.hpp @@ -12,6 +12,11 @@ #define __HOTPLACE_SDK_NOSTD__ #include +#include +#include +#include +#include +#include #include #endif diff --git a/test/nostd/sample.cpp b/test/nostd/sample.cpp index 0c8d4a5..9ec18a0 100644 --- a/test/nostd/sample.cpp +++ b/test/nostd/sample.cpp @@ -8,10 +8,13 @@ * Date Name Description */ +#include +#include #include #include using namespace hotplace; +using namespace hotplace::crypto; using namespace hotplace::io; using namespace hotplace::net; @@ -28,26 +31,182 @@ typedef struct _OPTION { t_shared_instance> _cmdline; void test_vector() { - t_vector v; - v.push_back(1); - v.push_back(2); - v.push_back(3); + _test_case.begin("vector"); basic_stream bs; - for_each>(v, [&](t_vector::const_iterator iter, int where) -> void { - switch (where) { - case 0: - bs << "[" << *iter; - break; - case 1: - bs << ", " << *iter; - break; - case 2: - bs << "]"; - break; - } - }); + + t_vector v1; + v1.push_back(1); + v1.push_back(2); + v1.push_back(3); + + _logger->writeln("case 1"); + print, basic_stream>(v1, bs); _logger->writeln(bs); + + _test_case.assert(3 == v1.size(), __FUNCTION__, "case 1"); + _test_case.assert((1 == v1[0]) && (2 == v1[1]) && (3 == v1[2]), __FUNCTION__, "case 2"); + + t_vector v2(v1); + t_vector v3(std::move(v1)); + + _test_case.assert(3 == v2.size(), __FUNCTION__, "case 3"); + _test_case.assert(3 == v3.size(), __FUNCTION__, "case 4"); + _test_case.assert(0 == v1.size(), __FUNCTION__, "case 5"); +} + +void test_list() { + _test_case.begin("list"); + + t_list l1; + l1.push_back(1); + l1.push_back(2); + l1.push_back(3); + + basic_stream bs; + print, basic_stream>(l1, bs); + _logger->writeln(bs); + + _test_case.assert(3 == l1.size(), __FUNCTION__, "case 1"); + _test_case.assert(1 == l1.front() && 3 == l1.back(), __FUNCTION__, "case 2"); + + t_list l2(l1); + t_list l3(std::move(l1)); + + _test_case.assert(3 == l2.size(), __FUNCTION__, "case 3"); + _test_case.assert(3 == l3.size(), __FUNCTION__, "case 4"); + _test_case.assert(0 == l1.size(), __FUNCTION__, "case 5"); +} + +void test_pq() { + _test_case.begin("binaryheap"); + + t_binary_heap heap; + openssl_prng prng; + basic_stream bs; + + std::vector table; + table.resize(10); + + for (size_t i = 0; i < 10; i++) { + table[i] = prng.rand32(); // expensive + } + + _test_case.assert(heap.size() == 0, __FUNCTION__, "random generated"); + + for (size_t i = 0; i < 10; i++) { + heap.push(table[i]); // fast + } + + _test_case.assert(heap.size() > 0, __FUNCTION__, "case 1"); + + bool errorcheck = false; + uint32 lastone = 0; + while (heap.size()) { + uint32 elem = heap.top(); + if (lastone > elem) { + errorcheck |= true; + } + heap.pop(); + } + + _test_case.assert(0 == heap.size(), __FUNCTION__, "case 2"); + _test_case.assert(false == errorcheck, __FUNCTION__, "case 3"); +} + +void test_graph() { + _test_case.begin("graph"); + t_graph g; + g.add_edge(1, 2) + .add_edge(1, 3) + .add_edge(1, 4) + .add_edge(2, 4) + .add_edge(2, 5) + .add_edge(3, 6) + .add_edge(4, 3) + .add_edge(4, 6) + .add_edge(4, 7) + .add_edge(5, 4) + .add_edge(5, 7) + .add_edge(7, 6); + + auto traverse_handler = [](const int& i, const std::vector& v) -> void { + basic_stream bs; + print, basic_stream>(v, bs, "(", ", ", ")"); + std::cout << bs << std::endl; + fflush(stdout); + }; + + auto adj = g.build_adjacent(); + // t_graph::t_graph_adjacent_list adj; + adj->learn().infer(); + adj->traverse(traverse_handler); + _test_case.assert(true, __FUNCTION__, "adjacent list #1"); + adj->traverse(2, traverse_handler); + _test_case.assert(true, __FUNCTION__, "adjacent list #2"); + + auto dfs = g.build_dfs(); + dfs->learn().infer(); + dfs->traverse(traverse_handler); + _test_case.assert(true, __FUNCTION__, "DFS #1"); + dfs->traverse(2, traverse_handler); + _test_case.assert(true, __FUNCTION__, "DFS #2"); + + auto bfs = g.build_bfs(); + bfs->learn().infer(); + bfs->traverse(traverse_handler); + _test_case.assert(true, __FUNCTION__, "BFS #1"); + bfs->traverse(2, traverse_handler); + _test_case.assert(true, __FUNCTION__, "BFS #2"); + + auto dijkstra = g.build_dijkstra(); + dijkstra->learn().infer(); + dijkstra->traverse(traverse_handler); + _test_case.assert(true, __FUNCTION__, "dijkstra #1"); + dijkstra->traverse(2, traverse_handler); + _test_case.assert(true, __FUNCTION__, "dijkstra #2"); +} + +void test_graph2() { + _test_case.begin("graph"); + t_graph g; + + g.add_edge("get up", "eat breakfast"); + + g.add_edge("eat breakfast", "brush teeath (morning)"); + g.add_edge("eat breakfast", "go to work"); + + g.add_edge("go to work", "go home"); + + g.add_edge("go home", "eat dinner"); + + g.add_edge("eat dinner", "brush teeath (evening)"); + g.add_edge("eat dinner", "watch tv"); + g.add_edge("eat dinner", "go to bed"); + + g.add_edge("go to bed", "dream"); + + auto traverse_handler = [](const std::string& i, const std::vector& v) -> void { + basic_stream bs; + print, basic_stream>(v, bs, "(", ", ", ")"); + std::cout << bs << std::endl; + fflush(stdout); + }; + + auto dfs = g.build_dfs(); + dfs->learn().infer(); + dfs->traverse("get up", traverse_handler); + _test_case.assert(true, __FUNCTION__, "DFS"); + + auto bfs = g.build_bfs(); + bfs->learn().infer(); + bfs->traverse("get up", traverse_handler); + _test_case.assert(true, __FUNCTION__, "BFS"); + + auto dijkstra = g.build_dijkstra(); + dijkstra->learn().infer(); + dijkstra->traverse("get up", traverse_handler); + _test_case.assert(true, __FUNCTION__, "dijkstra #2"); } int main(int argc, char** argv) { @@ -66,6 +225,10 @@ int main(int argc, char** argv) { _logger.make_share(builder.build()); test_vector(); + test_list(); + test_pq(); + test_graph(); + test_graph2(); _logger->flush();