1 /*
2  * Copyright (C) 2018 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 #include <hardware/hw_auth_token.h>
18 #include <keymasterV4_0/keymaster_utils.h>
19 
20 namespace android {
21 namespace hardware {
22 
operator <(const hidl_vec<uint8_t> & a,const hidl_vec<uint8_t> & b)23 inline static bool operator<(const hidl_vec<uint8_t>& a, const hidl_vec<uint8_t>& b) {
24     return memcmp(a.data(), b.data(), std::min(a.size(), b.size())) == -1;
25 }
26 
27 template <size_t SIZE>
operator <(const hidl_array<uint8_t,SIZE> & a,const hidl_array<uint8_t,SIZE> & b)28 inline static bool operator<(const hidl_array<uint8_t, SIZE>& a,
29                              const hidl_array<uint8_t, SIZE>& b) {
30     return memcmp(a.data(), b.data(), SIZE) == -1;
31 }
32 
33 namespace keymaster {
34 namespace V4_0 {
35 
operator <(const HmacSharingParameters & a,const HmacSharingParameters & b)36 bool operator<(const HmacSharingParameters& a, const HmacSharingParameters& b) {
37     return std::tie(a.seed, a.nonce) < std::tie(b.seed, b.nonce);
38 }
39 
40 namespace support {
41 
42 template <typename T, typename InIter>
copy_bytes_from_iterator(T * value,InIter src)43 inline static InIter copy_bytes_from_iterator(T* value, InIter src) {
44     uint8_t* value_ptr = reinterpret_cast<uint8_t*>(value);
45     std::copy(src, src + sizeof(T), value_ptr);
46     return src + sizeof(T);
47 }
48 
49 template <typename T, typename OutIter>
copy_bytes_to_iterator(const T & value,OutIter dest)50 inline static OutIter copy_bytes_to_iterator(const T& value, OutIter dest) {
51     const uint8_t* value_ptr = reinterpret_cast<const uint8_t*>(&value);
52     return std::copy(value_ptr, value_ptr + sizeof(value), dest);
53 }
54 
55 constexpr size_t kHmacSize = 32;
56 
authToken2HidlVec(const HardwareAuthToken & token)57 hidl_vec<uint8_t> authToken2HidlVec(const HardwareAuthToken& token) {
58     static_assert(1 /* version size */ + sizeof(token.challenge) + sizeof(token.userId) +
59                           sizeof(token.authenticatorId) + sizeof(token.authenticatorType) +
60                           sizeof(token.timestamp) + kHmacSize ==
61                       sizeof(hw_auth_token_t),
62                   "HardwareAuthToken content size does not match hw_auth_token_t size");
63 
64     hidl_vec<uint8_t> result;
65     result.resize(sizeof(hw_auth_token_t));
66     auto pos = result.begin();
67     *pos++ = 0;  // Version byte
68     pos = copy_bytes_to_iterator(token.challenge, pos);
69     pos = copy_bytes_to_iterator(token.userId, pos);
70     pos = copy_bytes_to_iterator(token.authenticatorId, pos);
71     auto auth_type = htonl(static_cast<uint32_t>(token.authenticatorType));
72     pos = copy_bytes_to_iterator(auth_type, pos);
73     auto timestamp = htonq(token.timestamp);
74     pos = copy_bytes_to_iterator(timestamp, pos);
75     if (token.mac.size() != kHmacSize) {
76         std::fill(pos, pos + kHmacSize, 0);
77     } else {
78         std::copy(token.mac.begin(), token.mac.end(), pos);
79     }
80 
81     return result;
82 }
83 
hidlVec2AuthToken(const hidl_vec<uint8_t> & buffer)84 HardwareAuthToken hidlVec2AuthToken(const hidl_vec<uint8_t>& buffer) {
85     HardwareAuthToken token;
86     static_assert(1 /* version size */ + sizeof(token.challenge) + sizeof(token.userId) +
87                           sizeof(token.authenticatorId) + sizeof(token.authenticatorType) +
88                           sizeof(token.timestamp) + kHmacSize ==
89                       sizeof(hw_auth_token_t),
90                   "HardwareAuthToken content size does not match hw_auth_token_t size");
91 
92     if (buffer.size() != sizeof(hw_auth_token_t)) return {};
93 
94     auto pos = buffer.begin();
95     ++pos;  // skip first byte
96     pos = copy_bytes_from_iterator(&token.challenge, pos);
97     pos = copy_bytes_from_iterator(&token.userId, pos);
98     pos = copy_bytes_from_iterator(&token.authenticatorId, pos);
99     pos = copy_bytes_from_iterator(&token.authenticatorType, pos);
100     token.authenticatorType = static_cast<HardwareAuthenticatorType>(
101         ntohl(static_cast<uint32_t>(token.authenticatorType)));
102     pos = copy_bytes_from_iterator(&token.timestamp, pos);
103     token.timestamp = ntohq(token.timestamp);
104     token.mac.resize(kHmacSize);
105     std::copy(pos, pos + kHmacSize, token.mac.data());
106 
107     return token;
108 }
109 
110 }  // namespace support
111 }  // namespace V4_0
112 }  // namespace keymaster
113 }  // namespace hardware
114 }  // namespace android
115