blob: 3543b87389f3827ef0650d7f874f95fcc6c91635 [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <stddef.h>
#include <stdint.h>
#include <sys/cdefs.h>
#if !defined(__INTRODUCED_IN)
#define __INTRODUCED_IN(__api_level) /* nothing */
#endif
// These APIs are for the Adb pairing protocol. This protocol requires both
// sides to possess a shared secret to authenticate each other. The connection
// is over TLS, and requires that both the client and server have a valid
// certificate.
//
// This protocol is one-to-one, i.e., one PairingConnectionCtx server instance
// interacts with only one PairingConnectionCtx client instance. In other words,
// every new client instance must be bound to a new server instance.
//
// If both sides have authenticated, they will exchange their peer information
// (see #PeerInfo).
__BEGIN_DECLS
#if !defined(__ANDROID__) || __ANDROID_API__ >= 30
const uint32_t kMaxPeerInfoSize = 8192;
struct PeerInfo {
uint8_t type;
uint8_t data[kMaxPeerInfoSize - 1];
} __attribute__((packed));
typedef struct PeerInfo PeerInfo;
static_assert(sizeof(PeerInfo) == kMaxPeerInfoSize, "PeerInfo has weird size");
enum PeerInfoType : uint8_t {
ADB_RSA_PUB_KEY = 0,
ADB_DEVICE_GUID = 1,
};
struct PairingConnectionCtx;
typedef struct PairingConnectionCtx PairingConnectionCtx;
typedef void (*pairing_result_cb)(const PeerInfo*, int, void*);
// Starts the pairing connection on a separate thread.
//
// Upon completion, if the pairing was successful,
// |cb| will be called with the peer information and certificate.
// Otherwise, |cb| will be called with empty data. |fd| should already
// be opened. PairingConnectionCtx will take ownership of the |fd|.
//
// Pairing is successful if both server/client uses the same non-empty
// |pswd|, and they are able to exchange the information. |pswd| and
// |certificate| must be non-empty. start() can only be called once in the
// lifetime of this object.
//
// @param ctx the PairingConnectionCtx instance. Will abort if null.
// @param fd the fd connecting the peers. This will take ownership of fd.
// @param cb the user-provided callback that is called with the result of the
// pairing. The callback will be called on a different thread from the
// caller.
// @param opaque opaque userdata.
// @return true if the thread was successfully started, false otherwise. To stop
// the connection process, destroy the instance (see
// #pairing_connection_destroy). If false is returned, cb will not be
// invoked. Otherwise, cb is guaranteed to be invoked, even if you
// destroy the ctx while in the pairing process.
bool pairing_connection_start(PairingConnectionCtx* ctx, int fd, pairing_result_cb cb, void* opaque)
__INTRODUCED_IN(30);
// Creates a new PairingConnectionCtx instance as the client.
//
// @param pswd the password to authenticate both peers. Will abort if null.
// @param pswd_len the length of pswd. Will abort if 0.
// @param peer_info the PeerInfo struct that is exchanged between peers if the
// pairing was successful. Will abort if null.
// @param x509_cert_pem the X.509 certificate in PEM format. Will abort if null.
// @param x509_size the size of x509_cert_pem. Will abort if 0.
// @param priv_key_pem the private key corresponding to the given X.509
// certificate, in PEM format. Will abort if null.
// @param priv_size the size of priv_key_pem. Will abort if 0.
// @return a new PairingConnectionCtx client instance. The caller is responsible
// for destroying the context via #pairing_connection_destroy.
PairingConnectionCtx* pairing_connection_client_new(const uint8_t* pswd, size_t pswd_len,
const PeerInfo* peer_info,
const uint8_t* x509_cert_pem, size_t x509_size,
const uint8_t* priv_key_pem, size_t priv_size)
__INTRODUCED_IN(30);
// Creates a new PairingConnectionCtx instance as the server.
//
// @param pswd the password to authenticate both peers. Will abort if null.
// @param pswd_len the length of pswd. Will abort if 0.
// @param peer_info the PeerInfo struct that is exchanged between peers if the
// pairing was successful. Will abort if null.
// @param x509_cert_pem the X.509 certificate in PEM format. Will abort if null.
// @param x509_size the size of x509_cert_pem. Will abort if 0.
// @param priv_key_pem the private key corresponding to the given X.509
// certificate, in PEM format. Will abort if null.
// @param priv_size the size of priv_key_pem. Will abort if 0.
// @return a new PairingConnectionCtx server instance. The caller is responsible
// for destroying the context via #pairing_connection_destroy.
PairingConnectionCtx* pairing_connection_server_new(const uint8_t* pswd, size_t pswd_len,
const PeerInfo* peer_info,
const uint8_t* x509_cert_pem, size_t x509_size,
const uint8_t* priv_key_pem, size_t priv_size)
__INTRODUCED_IN(30);
// Destroys the PairingConnectionCtx instance.
//
// It is safe to destroy the instance at any point in the pairing process.
//
// @param ctx the PairingConnectionCtx instance to destroy. Will abort if null.
void pairing_connection_destroy(PairingConnectionCtx* ctx) __INTRODUCED_IN(30);
#endif //!__ANDROID__ || __ANDROID_API__ >= 30
__END_DECLS