1 /*
2  * Copyright 2021, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <array>
20 #include <cstdint>
21 
22 namespace cuttlefish {
23 namespace confui {
24 namespace support {
25 using auth_token_key_t = std::array<std::uint8_t, 32>;
26 using hmac_t = auth_token_key_t;
27 
28 template <typename T>
29 auto bytes_cast(const T& v) -> const uint8_t (&)[sizeof(T)] {
30   return *reinterpret_cast<const uint8_t(*)[sizeof(T)]>(&v);
31 }
32 template <typename T>
33 auto bytes_cast(T& v) -> uint8_t (&)[sizeof(T)] {
34   return *reinterpret_cast<uint8_t(*)[sizeof(T)]>(&v);
35 }
36 
37 template <typename IntType, uint32_t byteOrder>
38 struct choose_hton;
39 
40 template <typename IntType>
41 struct choose_hton<IntType, __ORDER_LITTLE_ENDIAN__> {
42   inline static IntType hton(const IntType& value) {
43     IntType result = {};
44     const unsigned char* inbytes =
45         reinterpret_cast<const unsigned char*>(&value);
46     unsigned char* outbytes = reinterpret_cast<unsigned char*>(&result);
47     for (int i = sizeof(IntType) - 1; i >= 0; --i) {
48       *(outbytes++) = inbytes[i];
49     }
50     return result;
51   }
52 };
53 
54 template <typename IntType>
55 struct choose_hton<IntType, __ORDER_BIG_ENDIAN__> {
56   inline static IntType hton(const IntType& value) { return value; }
57 };
58 
59 template <typename IntType>
60 inline IntType hton(const IntType& value) {
61   return choose_hton<IntType, __BYTE_ORDER__>::hton(value);
62 }
63 
64 class ByteBufferProxy {
65   template <typename T>
66   struct has_data {
67     template <typename U>
68     static int f(const U*, const void*) {
69       return 0;
70     }
71     template <typename U>
72     static int* f(const U* u, decltype(u->data())) {
73       return nullptr;
74     }
75     static constexpr bool value =
76         std::is_pointer<decltype(f((T*)nullptr, ""))>::value;
77   };
78 
79  public:
80   template <typename T>
81   ByteBufferProxy(const T& buffer, decltype(buffer.data()) = nullptr)
82       : data_(reinterpret_cast<const uint8_t*>(buffer.data())),
83         size_(buffer.size()) {
84     static_assert(sizeof(decltype(*buffer.data())) == 1, "elements to large");
85   }
86 
87   // this overload kicks in for types that have .c_str() but not .data(), such
88   // as hidl_string. std::string has both so we need to explicitly disable this
89   // overload if .data() is present.
90   template <typename T>
91   ByteBufferProxy(
92       const T& buffer,
93       std::enable_if_t<!has_data<T>::value, decltype(buffer.c_str())> = nullptr)
94       : data_(reinterpret_cast<const uint8_t*>(buffer.c_str())),
95         size_(buffer.size()) {
96     static_assert(sizeof(decltype(*buffer.c_str())) == 1, "elements to large");
97   }
98 
99   template <size_t size>
100   ByteBufferProxy(const char (&buffer)[size])
101       : data_(reinterpret_cast<const uint8_t*>(buffer)), size_(size - 1) {
102     static_assert(size > 0, "even an empty string must be 0-terminated");
103   }
104 
105   template <size_t size>
106   ByteBufferProxy(const uint8_t (&buffer)[size]) : data_(buffer), size_(size) {}
107 
108   ByteBufferProxy() : data_(nullptr), size_(0) {}
109 
110   const uint8_t* data() const { return data_; }
111   size_t size() const { return size_; }
112 
113   const uint8_t* begin() const { return data_; }
114   const uint8_t* end() const { return data_ + size_; }
115 
116  private:
117   const uint8_t* data_;
118   size_t size_;
119 };
120 
121 // copied from:
122 // hardware/interface/confirmationui/support/include/android/hardware/confirmationui/support/confirmationui_utils.h
123 
124 }  // end of namespace support
125 }  // end of namespace confui
126 }  // end of namespace cuttlefish
127