blob: 9ef97e2600bda312f647c03123c4be10e8a2bbcb [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
__BEGIN_DECLS
#if !defined(__ANDROID__) || __ANDROID_API__ >= 30
/**
* PairingAuthCtx is a wrapper around the SPAKE2 protocol + cipher initialization
* for encryption. On construction, the |password| will be used to generate a
* SPAKE2 message. Each peer will exchange the messages in |pairing_auth_get_msg|
* to initialize their ciphers in |pairing_auth_init_cipher|. If both peers used the
* same |password|, then both sides will be able to decrypt each other's messages.
*
* On creation of a PairingAuthCtx, |pairing_auth_init_cipher| prior to using
* the encrypt and decrypt APIs. Furthermore, you can only initialize the cipher
* once.
*
* See pairing_auth_test.cpp for example usage.
*
*/
struct PairingAuthCtx;
typedef struct PairingAuthCtx PairingAuthCtx;
/**
* Creates a new PairingAuthCtx instance as the server.
*
* @param pswd the shared secret the server and client use to authenticate each
* other. Will abort if null.
* @param len the length of the pswd in bytes. Will abort if 0.
* @return a new PairingAuthCtx server instance. Caller is responsible for
* destroying the context via #pairing_auth_destroy.
*/
PairingAuthCtx* pairing_auth_server_new(const uint8_t* pswd, size_t len) __INTRODUCED_IN(30);
/**
* Creates a new PairingAuthCtx instance as the client.
*
* @param pswd the shared secret the server and client use to authenticate each
* other. Will abort if null.
* @param len the length of the pswd in bytes. Will abort if 0.
* @return a new PairingAuthCtx client instance. Caller is responsible for
* destroying the context via #pairing_auth_destroy.
*/
PairingAuthCtx* pairing_auth_client_new(const uint8_t* pswd, size_t len) __INTRODUCED_IN(30);
/**
* Destroys the PairingAuthCtx.
*
* @param ctx the PairingAuthCtx instance to destroy. Will abort if null.
*/
void pairing_auth_destroy(PairingAuthCtx* ctx) __INTRODUCED_IN(30);
/**
* Returns the exact size of the SPAKE2 msg.
*
* Use this size as the buffer size when retrieving the message via
* #pairing_auth_get_msg.
*
* @param ctx the PairingAuthCtx instance. Will abort if null.
* @return the size of the SPAKE2 message in bytes. This is guaranteed to be > 0.
*/
size_t pairing_auth_msg_size(PairingAuthCtx* ctx) __INTRODUCED_IN(30);
/**
* Writes the SPAKE2 message to exchange with the other party to |out_buf|.
*
* This is guaranteed to write a valid message to |out_buf|. Use #pairing_auth_msg_size
* to get the size the |out_buf| should be. The SPAKE2 messages will be used to
* initialize the cipher for encryption/decryption (see #pairing_auth_init_cipher).
*
* @param ctx the PairingAuthCtx instance. Will abort if null.
* @param out_buf the buffer the message is written to. The buffer is assumed to
* be have at least #pairing_auth_msg_size size. Will abort if
* out_buf is null.
*/
void pairing_auth_get_spake2_msg(PairingAuthCtx* ctx, uint8_t* out_buf) __INTRODUCED_IN(30);
/**
* Processes the peer's |their_msg| and attempts to initialize the cipher for
* encryption.
*
* You can only call this method ONCE with a non-empty |msg|, regardless of success
* or failure. On success, you can use the #pairing_auth_decrypt and #pairing_auth_encrypt
* methods to exchange any further information securely. On failure, this
* PairingAuthCtx instance has no more purpose and should be destroyed.
*
* @param ctx the PairingAuthCtx instance. Will abort if null.
* @param their_msg the peer's SPAKE2 msg. See #pairing_auth_get_msg. Will abort
* if null.
* @param msg_len the length of their_msg in bytes. Will abort if 0.
* @return true iff the client and server used the same password when creating
* the PairingAuthCtx. See
* https: *commondatastorage.googleapis.com/chromium-boringssl-docs/curve25519.h.html#SPAKE2
* for more details on the SPAKE2 protocol.
*/
bool pairing_auth_init_cipher(PairingAuthCtx* ctx, const uint8_t* their_msg, size_t msg_len)
__INTRODUCED_IN(30);
/**
* Returns a safe buffer size for encrypting data of a certain size.
*
* IMPORTANT: This will abort if either #pairing_auth_init_cipher was not called
* or #pairing_auth_init_cipher failed.
*
* @param ctx the PairingAuthCtx instance. Will abort if null.
* @param len the size of the message wanting to encrypt in bytes.
* @return the minimum buffer size, in bytes, to hold an encrypted message of size len. See
* #pairing_auth_encrypt for usage.
*/
size_t pairing_auth_safe_encrypted_size(PairingAuthCtx* ctx, size_t len) __INTRODUCED_IN(30);
/**
* Encrypts input data and writes the encrypted data into a user-provided buffer.
*
* IMPORTANT: This will abort if either #pairing_auth_init_cipher was not called
* or #pairing_auth_init_cipher failed.
*
* @param ctx the PairingAuthCtx instance. Will abort if null.
* @param inbuf the buffer containing the data to encrypt. Will abort if null.
* @param inlen the size of inbuf in bytes. Will abort if 0.
* @param outbuf the buffer to write the encrypted data to. Will abort if null
* @param outlen the size of outbuf in bytes. See #pairing_auth_safe_encrypted_size.
* @return true if all the data was encrypted and written to outbuf, false
* otherwise.
*/
bool pairing_auth_encrypt(PairingAuthCtx* ctx, const uint8_t* inbuf, size_t inlen, uint8_t* outbuf,
size_t* outlen) __INTRODUCED_IN(30);
/**
* Returns a safe buffer size for decrypting data of a certain size.
*
* IMPORTANT: This will abort if either #pairing_auth_init_cipher was not called
* or #pairing_auth_init_cipher failed.
*
* @param ctx the PairingAuthCtx instance. Will abort if null.
* @param buf the buffer containing the encrypted data. Will abort if null.
* @param len the size of the buf in bytes. Will abort if 0.
* @return the minimum buffer size, in bytes, to hold a decrypted message of size len. See
* #pairing_auth_decrypt for usage.
*/
size_t pairing_auth_safe_decrypted_size(PairingAuthCtx* ctx, const uint8_t* buf, size_t len)
__INTRODUCED_IN(30);
/**
* Decrypts input data and writes the decrypted data into a user-provided buffer.
*
* IMPORTANT: This will abort if either #pairing_auth_init_cipher was not called
* or #pairing_auth_init_cipher failed.
*
* @param ctx the PairingAuthCtx instance. Will abort if null.
* @param inbuf the buffer containing the data to decrypt. Will abort if null.
* @param inlen the size of inbuf in bytes. WIll abort if 0.
* @param outbuf the buffer to write the decrypted data to. Will abort if null.
* @param outlen the size of outbuf in bytes. See #pairing_auth_safe_decrypted_size.
* Will abort if 0.
* @return true if all the data was decrypted and written to outbuf, false
* otherwise.
*/
bool pairing_auth_decrypt(PairingAuthCtx* ctx, const uint8_t* inbuf, size_t inlen, uint8_t* outbuf,
size_t* outlen) __INTRODUCED_IN(30);
#endif //!__ANDROID__ || __ANDROID_API__ >= 30
__END_DECLS