• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 "adb/pairing/pairing_auth.h"
18 
19 #include <android-base/logging.h>
20 
21 #include <openssl/curve25519.h>
22 #include <openssl/mem.h>
23 
24 #include <iomanip>
25 #include <sstream>
26 #include <vector>
27 
28 #include "adb/pairing/aes_128_gcm.h"
29 
30 using namespace adb::pairing;
31 
32 static constexpr spake2_role_t kClientRole = spake2_role_alice;
33 static constexpr spake2_role_t kServerRole = spake2_role_bob;
34 
35 static const uint8_t kClientName[] = "adb pair client";
36 static const uint8_t kServerName[] = "adb pair server";
37 
38 // This class is basically a wrapper around the SPAKE2 protocol + initializing a
39 // cipher with the generated key material for encryption.
40 struct PairingAuthCtx {
41   public:
42     using Data = std::vector<uint8_t>;
43     enum class Role {
44         Client,
45         Server,
46     };
47 
48     explicit PairingAuthCtx(Role role, const Data& pswd);
49 
50     // Returns the message to exchange with the other party. This is guaranteed
51     // to have a non-empty message if creating this object with
52     // |PairingAuthCtx::Create|, so you won't need to check.
53     const Data& msg() const;
54 
55     // Processes the peer's |msg| and attempts to initialize the cipher for
56     // encryption. You can only call this method ONCE with a non-empty |msg|,
57     // regardless of success or failure. Subsequent calls will always return
58     // false. On success, you can use the |decrypt|
59     // and |encrypt| methods to exchange any further information securely.
60     //
61     // Note: Once you call this with a non-empty key, the state is locked, which
62     // means that you cannot try and register another key, regardless of the
63     // return value. In order to register another key, you have to create a new
64     // instance of PairingAuthCtx.
65     bool InitCipher(const Data& their_msg);
66 
67     // Encrypts |data| and returns the result. If encryption fails, the return
68     // will be an empty vector.
69     Data Encrypt(const Data& data);
70 
71     // Decrypts |data| and returns the result. If decryption fails, the return
72     // will be an empty vector.
73     Data Decrypt(const Data& data);
74 
75     // Returns a safe buffer size for encrypting a buffer of size |len|.
76     size_t SafeEncryptedSize(size_t len);
77 
78     // Returns a safe buffer size for decrypting a buffer of size |len|.
79     size_t SafeDecryptedSize(size_t len);
80 
81   private:
82     Data our_msg_;
83     Role role_;
84     bssl::UniquePtr<SPAKE2_CTX> spake2_ctx_;
85     std::unique_ptr<Aes128Gcm> cipher_;
86 };  // PairingAuthCtx
87 
PairingAuthCtx(Role role,const Data & pswd)88 PairingAuthCtx::PairingAuthCtx(Role role, const Data& pswd) : role_(role) {
89     CHECK(!pswd.empty());
90     // Try to create the spake2 context and generate the public key.
91     spake2_role_t spake_role;
92     const uint8_t* my_name = nullptr;
93     const uint8_t* their_name = nullptr;
94     size_t my_len = 0;
95     size_t their_len = 0;
96 
97     // Create the SPAKE2 context
98     switch (role_) {
99         case Role::Client:
100             spake_role = kClientRole;
101             my_name = kClientName;
102             my_len = sizeof(kClientName);
103             their_name = kServerName;
104             their_len = sizeof(kServerName);
105             break;
106         case Role::Server:
107             spake_role = kServerRole;
108             my_name = kServerName;
109             my_len = sizeof(kServerName);
110             their_name = kClientName;
111             their_len = sizeof(kClientName);
112             break;
113     }
114     spake2_ctx_.reset(SPAKE2_CTX_new(spake_role, my_name, my_len, their_name, their_len));
115     if (spake2_ctx_ == nullptr) {
116         LOG(ERROR) << "Unable to create a SPAKE2 context.";
117         return;
118     }
119 
120     // Generate the SPAKE2 public key
121     size_t key_size = 0;
122     uint8_t key[SPAKE2_MAX_MSG_SIZE];
123     int status = SPAKE2_generate_msg(spake2_ctx_.get(), key, &key_size, SPAKE2_MAX_MSG_SIZE,
124                                      pswd.data(), pswd.size());
125     if (status != 1 || key_size == 0) {
126         LOG(ERROR) << "Unable to generate the SPAKE2 public key.";
127         return;
128     }
129     our_msg_.assign(key, key + key_size);
130 }
131 
msg() const132 const PairingAuthCtx::Data& PairingAuthCtx::msg() const {
133     return our_msg_;
134 }
135 
InitCipher(const PairingAuthCtx::Data & their_msg)136 bool PairingAuthCtx::InitCipher(const PairingAuthCtx::Data& their_msg) {
137     // You can only register a key once.
138     CHECK(!their_msg.empty());
139     CHECK(!cipher_);
140 
141     // Don't even try to process a message over the SPAKE2_MAX_MSG_SIZE
142     if (their_msg.size() > SPAKE2_MAX_MSG_SIZE) {
143         LOG(ERROR) << "their_msg size [" << their_msg.size() << "] greater then max size ["
144                    << SPAKE2_MAX_MSG_SIZE << "].";
145         return false;
146     }
147 
148     size_t key_material_len = 0;
149     uint8_t key_material[SPAKE2_MAX_KEY_SIZE];
150     int status = SPAKE2_process_msg(spake2_ctx_.get(), key_material, &key_material_len,
151                                     sizeof(key_material), their_msg.data(), their_msg.size());
152     if (status != 1) {
153         LOG(ERROR) << "Unable to process their public key";
154         return false;
155     }
156 
157     // Once SPAKE2_process_msg returns successfully, you can't do anything else
158     // with the context, besides destroy it.
159     cipher_.reset(new Aes128Gcm(key_material, key_material_len));
160 
161     return true;
162 }
163 
Encrypt(const PairingAuthCtx::Data & data)164 PairingAuthCtx::Data PairingAuthCtx::Encrypt(const PairingAuthCtx::Data& data) {
165     CHECK(cipher_);
166     CHECK(!data.empty());
167 
168     // Determine the size for the encrypted data based on the raw data.
169     Data encrypted(cipher_->EncryptedSize(data.size()));
170     auto out_size = cipher_->Encrypt(data.data(), data.size(), encrypted.data(), encrypted.size());
171     if (!out_size.has_value() || *out_size == 0) {
172         LOG(ERROR) << "Unable to encrypt data";
173         return Data();
174     }
175     encrypted.resize(*out_size);
176 
177     return encrypted;
178 }
179 
Decrypt(const PairingAuthCtx::Data & data)180 PairingAuthCtx::Data PairingAuthCtx::Decrypt(const PairingAuthCtx::Data& data) {
181     CHECK(cipher_);
182     CHECK(!data.empty());
183 
184     // Determine the size for the decrypted data based on the raw data.
185     Data decrypted(cipher_->DecryptedSize(data.size()));
186     size_t decrypted_size = decrypted.size();
187     auto out_size = cipher_->Decrypt(data.data(), data.size(), decrypted.data(), decrypted_size);
188     if (!out_size.has_value() || *out_size == 0) {
189         LOG(ERROR) << "Unable to decrypt data";
190         return Data();
191     }
192     decrypted.resize(*out_size);
193 
194     return decrypted;
195 }
196 
SafeEncryptedSize(size_t len)197 size_t PairingAuthCtx::SafeEncryptedSize(size_t len) {
198     CHECK(cipher_);
199     return cipher_->EncryptedSize(len);
200 }
201 
SafeDecryptedSize(size_t len)202 size_t PairingAuthCtx::SafeDecryptedSize(size_t len) {
203     CHECK(cipher_);
204     return cipher_->DecryptedSize(len);
205 }
206 
pairing_auth_server_new(const uint8_t * pswd,size_t len)207 PairingAuthCtx* pairing_auth_server_new(const uint8_t* pswd, size_t len) {
208     CHECK(pswd);
209     CHECK_GT(len, 0U);
210     std::vector<uint8_t> p(pswd, pswd + len);
211     auto* ret = new PairingAuthCtx(PairingAuthCtx::Role::Server, std::move(p));
212     CHECK(!ret->msg().empty());
213     return ret;
214 }
215 
pairing_auth_client_new(const uint8_t * pswd,size_t len)216 PairingAuthCtx* pairing_auth_client_new(const uint8_t* pswd, size_t len) {
217     CHECK(pswd);
218     CHECK_GT(len, 0U);
219     std::vector<uint8_t> p(pswd, pswd + len);
220     auto* ret = new PairingAuthCtx(PairingAuthCtx::Role::Client, std::move(p));
221     CHECK(!ret->msg().empty());
222     return ret;
223 }
224 
pairing_auth_msg_size(PairingAuthCtx * ctx)225 size_t pairing_auth_msg_size(PairingAuthCtx* ctx) {
226     CHECK(ctx);
227     return ctx->msg().size();
228 }
229 
pairing_auth_get_spake2_msg(PairingAuthCtx * ctx,uint8_t * out_buf)230 void pairing_auth_get_spake2_msg(PairingAuthCtx* ctx, uint8_t* out_buf) {
231     CHECK(ctx);
232     CHECK(out_buf);
233     auto& msg = ctx->msg();
234     memcpy(out_buf, msg.data(), msg.size());
235 }
236 
pairing_auth_init_cipher(PairingAuthCtx * ctx,const uint8_t * their_msg,size_t msg_len)237 bool pairing_auth_init_cipher(PairingAuthCtx* ctx, const uint8_t* their_msg, size_t msg_len) {
238     CHECK(ctx);
239     CHECK(their_msg);
240     CHECK_GT(msg_len, 0U);
241 
242     std::vector<uint8_t> p(their_msg, their_msg + msg_len);
243     return ctx->InitCipher(p);
244 }
245 
pairing_auth_safe_encrypted_size(PairingAuthCtx * ctx,size_t len)246 size_t pairing_auth_safe_encrypted_size(PairingAuthCtx* ctx, size_t len) {
247     CHECK(ctx);
248     return ctx->SafeEncryptedSize(len);
249 }
250 
pairing_auth_encrypt(PairingAuthCtx * ctx,const uint8_t * inbuf,size_t inlen,uint8_t * outbuf,size_t * outlen)251 bool pairing_auth_encrypt(PairingAuthCtx* ctx, const uint8_t* inbuf, size_t inlen, uint8_t* outbuf,
252                           size_t* outlen) {
253     CHECK(ctx);
254     CHECK(inbuf);
255     CHECK(outbuf);
256     CHECK(outlen);
257     CHECK_GT(inlen, 0U);
258 
259     std::vector<uint8_t> in(inbuf, inbuf + inlen);
260     auto out = ctx->Encrypt(in);
261     if (out.empty()) {
262         return false;
263     }
264 
265     memcpy(outbuf, out.data(), out.size());
266     *outlen = out.size();
267     return true;
268 }
269 
pairing_auth_safe_decrypted_size(PairingAuthCtx * ctx,const uint8_t * buf,size_t len)270 size_t pairing_auth_safe_decrypted_size(PairingAuthCtx* ctx, const uint8_t* buf, size_t len) {
271     CHECK(ctx);
272     CHECK(buf);
273     CHECK_GT(len, 0U);
274     // We no longer need buf for EVP_AEAD
275     return ctx->SafeDecryptedSize(len);
276 }
277 
pairing_auth_decrypt(PairingAuthCtx * ctx,const uint8_t * inbuf,size_t inlen,uint8_t * outbuf,size_t * outlen)278 bool pairing_auth_decrypt(PairingAuthCtx* ctx, const uint8_t* inbuf, size_t inlen, uint8_t* outbuf,
279                           size_t* outlen) {
280     CHECK(ctx);
281     CHECK(inbuf);
282     CHECK(outbuf);
283     CHECK(outlen);
284     CHECK_GT(inlen, 0U);
285 
286     std::vector<uint8_t> in(inbuf, inbuf + inlen);
287     auto out = ctx->Decrypt(in);
288     if (out.empty()) {
289         return false;
290     }
291 
292     memcpy(outbuf, out.data(), out.size());
293     *outlen = out.size();
294     return true;
295 }
296 
pairing_auth_destroy(PairingAuthCtx * ctx)297 void pairing_auth_destroy(PairingAuthCtx* ctx) {
298     CHECK(ctx);
299     delete ctx;
300 }
301