1 /*
2  *
3  * Copyright 2019, The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #ifndef TEEUI_GENERICMESSAGES_H_
19 #define TEEUI_GENERICMESSAGES_H_
20 
21 #include <limits>
22 #include <tuple>
23 
24 #include <stdint.h>
25 
26 #include <teeui/common_message_types.h>
27 #include <teeui/msg_formatting.h>
28 
29 namespace teeui {
30 
31 enum class Command : uint32_t {
32     Invalid,
33     PromptUserConfirmation,
34     FetchConfirmationResult,
35     DeliverTestCommand,
36     Abort,
37 };
38 
39 using Protocol = uint32_t;
40 
41 template <Protocol Proto, typename CmdT, CmdT cmd> struct Cmd {};
42 
43 static constexpr const Protocol kProtoGeneric = 0;
44 static constexpr const Protocol kProtoInvalid = std::numeric_limits<Protocol>::max();
45 
46 #define DECLARE_GENERIC_COMMAND(cmd) using Cmd##cmd = Cmd<kProtoGeneric, Command, Command::cmd>
47 
48 DECLARE_GENERIC_COMMAND(PromptUserConfirmation);
49 DECLARE_GENERIC_COMMAND(FetchConfirmationResult);
50 DECLARE_GENERIC_COMMAND(DeliverTestCommand);
51 DECLARE_GENERIC_COMMAND(Abort);
52 
53 using PromptUserConfirmationMsg = Message<CmdPromptUserConfirmation, MsgString, MsgVector<uint8_t>,
54                                           MsgString, MsgVector<UIOption>>;
55 using PromptUserConfirmationResponse = Message<ResponseCode>;
56 using DeliverTestCommandMessage = Message<CmdDeliverTestCommand, TestModeCommands>;
57 using DeliverTestCommandResponse = Message<ResponseCode>;
58 using AbortMsg = Message<CmdAbort>;
59 using ResultMsg = Message<ResponseCode, MsgVector<uint8_t>, MsgVector<uint8_t>>;
60 using FetchConfirmationResult = Message<CmdFetchConfirmationResult>;
61 
62 template <uint32_t proto, typename CmdT, CmdT cmd>
write(WriteStream out,Cmd<proto,CmdT,cmd>)63 inline WriteStream write(WriteStream out, Cmd<proto, CmdT, cmd>) {
64     volatile Protocol* protoptr = reinterpret_cast<volatile Protocol*>(out.pos());
65     out += sizeof(Protocol);
66     if (out) *protoptr = proto;
67 
68     volatile CmdT* cmdptr = reinterpret_cast<volatile CmdT*>(out.pos());
69     out += sizeof(CmdT);
70     if (out) *cmdptr = cmd;
71 
72     return out;
73 }
74 
75 template <typename CmdSpec, typename... Tail>
write(Message<CmdSpec,Tail...>,WriteStream out,const Tail &...tail)76 WriteStream write(Message<CmdSpec, Tail...>, WriteStream out, const Tail&... tail) {
77     out = write(out, CmdSpec());
78     return write(Message<Tail...>(), out, tail...);
79 }
80 
81 template <Protocol proto, typename CmdT, CmdT cmd, typename... Fields>
read(Message<Cmd<proto,CmdT,cmd>,Fields...>,ReadStream in)82 std::tuple<ReadStream, Fields...> read(Message<Cmd<proto, CmdT, cmd>, Fields...>, ReadStream in) {
83     return read(Message<Fields...>(), in);
84 }
85 
86 template <Protocol proto, typename CmdT, CmdT cmd, typename... T>
87 struct msg2tuple<Message<Cmd<proto, CmdT, cmd>, T...>> {
88     using type = std::tuple<T...>;
89 };
90 
91 std::tuple<ReadStream, uint32_t> readU32(ReadStream in);
92 
93 template <typename CmdT, CmdT Invalid = CmdT::Invalid>
94 std::tuple<ReadStream, CmdT> readCmd(ReadStream in) {
95     static_assert(sizeof(CmdT) == sizeof(uint32_t),
96                   "Can only be used with types the size of uint32_t");
97     auto [stream, value] = readU32(in);
98     if (stream) return {stream, CmdT(value)};
99     return {stream, Invalid};
100 }
101 
102 template <typename CmdT, CmdT Invalid = CmdT::Invalid> CmdT peakCmd(ReadStream in) {
103     auto [_, cmd] = readCmd<CmdT>(in);
104     return cmd;
105 }
106 
107 std::tuple<ReadStream, Command> readCommand(ReadStream in);
108 Command peakCommand(ReadStream in);
109 std::tuple<ReadStream, Protocol> readProtocol(ReadStream in);
110 Protocol peakProtocol(ReadStream in);
111 
112 }  // namespace teeui
113 
114 #endif  // TEEUI_GENERICMESSAGES_H_
115