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 #pragma once
18 
19 #include <stddef.h>
20 #include <stdint.h>
21 #include <sys/cdefs.h>
22 
23 #if !defined(__INTRODUCED_IN)
24 #define __INTRODUCED_IN(__api_level) /* nothing */
25 #endif
26 
27 __BEGIN_DECLS
28 
29 /**
30  * PairingAuthCtx is a wrapper around the SPAKE2 protocol + cipher initialization
31  * for encryption. On construction, the |password| will be used to generate a
32  * SPAKE2 message. Each peer will exchange the messages in |pairing_auth_get_msg|
33  * to initialize their ciphers in |pairing_auth_init_cipher|. If both peers used the
34  * same |password|, then both sides will be able to decrypt each other's messages.
35  *
36  * On creation of a PairingAuthCtx, |pairing_auth_init_cipher| prior to using
37  * the encrypt and decrypt APIs. Furthermore, you can only initialize the cipher
38  * once.
39  *
40  * See pairing_auth_test.cpp for example usage.
41  *
42  */
43 struct PairingAuthCtx;
44 typedef struct PairingAuthCtx PairingAuthCtx;
45 
46 /**
47  * Creates a new PairingAuthCtx instance as the server.
48  *
49  * @param pswd the shared secret the server and client use to authenticate each
50  *             other. Will abort if null.
51  * @param len the length of the pswd in bytes. Will abort if 0.
52  * @return a new PairingAuthCtx server instance. Caller is responsible for
53  *         destroying the context via #pairing_auth_destroy.
54  */
55 PairingAuthCtx* pairing_auth_server_new(const uint8_t* pswd, size_t len) __INTRODUCED_IN(30);
56 
57 /**
58  * Creates a new PairingAuthCtx instance as the client.
59  *
60  * @param pswd the shared secret the server and client use to authenticate each
61  *             other. Will abort if null.
62  * @param len the length of the pswd in bytes. Will abort if 0.
63  * @return a new PairingAuthCtx client instance. Caller is responsible for
64  *         destroying the context via #pairing_auth_destroy.
65  */
66 PairingAuthCtx* pairing_auth_client_new(const uint8_t* pswd, size_t len) __INTRODUCED_IN(30);
67 
68 /**
69  * Destroys the PairingAuthCtx.
70  *
71  * @param ctx the PairingAuthCtx instance to destroy. Will abort if null.
72  */
73 void pairing_auth_destroy(PairingAuthCtx* ctx) __INTRODUCED_IN(30);
74 
75 /**
76  * Returns the exact size of the SPAKE2 msg.
77  *
78  * Use this size as the buffer size when retrieving the message via
79  * #pairing_auth_get_msg.
80  *
81  * @param ctx the PairingAuthCtx instance. Will abort if null.
82  * @return the size of the SPAKE2 message in bytes. This is guaranteed to be > 0.
83  */
84 size_t pairing_auth_msg_size(PairingAuthCtx* ctx) __INTRODUCED_IN(30);
85 
86 /**
87  * Writes the SPAKE2 message to exchange with the other party to |out_buf|.
88  *
89  * This is guaranteed to write a valid message to |out_buf|. Use #pairing_auth_msg_size
90  * to get the size the |out_buf| should be. The SPAKE2 messages will be used to
91  * initialize the cipher for encryption/decryption (see #pairing_auth_init_cipher).
92  *
93  * @param ctx the PairingAuthCtx instance. Will abort if null.
94  * @param out_buf the buffer the message is written to. The buffer is assumed to
95  *                be have at least #pairing_auth_msg_size size. Will abort if
96  *                out_buf is null.
97  */
98 void pairing_auth_get_spake2_msg(PairingAuthCtx* ctx, uint8_t* out_buf) __INTRODUCED_IN(30);
99 
100 /**
101  * Processes the peer's |their_msg| and attempts to initialize the cipher for
102  * encryption.
103  *
104  * You can only call this method ONCE with a non-empty |msg|, regardless of success
105  * or failure. On success, you can use the #pairing_auth_decrypt and #pairing_auth_encrypt
106  * methods to exchange any further information securely. On failure, this
107  * PairingAuthCtx instance has no more purpose and should be destroyed.
108  *
109  * @param ctx the PairingAuthCtx instance. Will abort if null.
110  * @param their_msg the peer's SPAKE2 msg. See #pairing_auth_get_msg. Will abort
111  *        if null.
112  * @param msg_len the length of their_msg in bytes. Will abort if 0.
113  * @return true iff the client and server used the same password when creating
114  *         the PairingAuthCtx. See
115  *         https: *commondatastorage.googleapis.com/chromium-boringssl-docs/curve25519.h.html#SPAKE2
116  *         for more details on the SPAKE2 protocol.
117  */
118 bool pairing_auth_init_cipher(PairingAuthCtx* ctx, const uint8_t* their_msg, size_t msg_len)
119         __INTRODUCED_IN(30);
120 
121 /**
122  * Returns a safe buffer size for encrypting data of a certain size.
123  *
124  * IMPORTANT: This will abort if either #pairing_auth_init_cipher was not called
125  * or #pairing_auth_init_cipher failed.
126  *
127  * @param ctx the PairingAuthCtx instance. Will abort if null.
128  * @param len the size of the message wanting to encrypt in bytes.
129  * @return the minimum buffer size, in bytes, to hold an encrypted message of size len. See
130  * #pairing_auth_encrypt for usage.
131  */
132 size_t pairing_auth_safe_encrypted_size(PairingAuthCtx* ctx, size_t len) __INTRODUCED_IN(30);
133 
134 /**
135  * Encrypts input data and writes the encrypted data into a user-provided buffer.
136  *
137  * IMPORTANT: This will abort if either #pairing_auth_init_cipher was not called
138  * or #pairing_auth_init_cipher failed.
139  *
140  * @param ctx the PairingAuthCtx instance. Will abort if null.
141  * @param inbuf the buffer containing the data to encrypt. Will abort if null.
142  * @param inlen the size of inbuf in bytes. Will abort if 0.
143  * @param outbuf the buffer to write the encrypted data to. Will abort if null
144  * @param outlen the size of outbuf in bytes. See #pairing_auth_safe_encrypted_size.
145  * @return true if all the data was encrypted and written to outbuf, false
146  *         otherwise.
147  */
148 bool pairing_auth_encrypt(PairingAuthCtx* ctx, const uint8_t* inbuf, size_t inlen, uint8_t* outbuf,
149                           size_t* outlen) __INTRODUCED_IN(30);
150 
151 /**
152  * Returns a safe buffer size for decrypting data of a certain size.
153  *
154  * IMPORTANT: This will abort if either #pairing_auth_init_cipher was not called
155  * or #pairing_auth_init_cipher failed.
156  *
157  * @param ctx the PairingAuthCtx instance. Will abort if null.
158  * @param buf the buffer containing the encrypted data. Will abort if null.
159  * @param len the size of the buf in bytes. Will abort if 0.
160  * @return the minimum buffer size, in bytes, to hold a decrypted message of size len. See
161  *         #pairing_auth_decrypt for usage.
162  */
163 size_t pairing_auth_safe_decrypted_size(PairingAuthCtx* ctx, const uint8_t* buf, size_t len)
164         __INTRODUCED_IN(30);
165 
166 /**
167  * Decrypts input data and writes the decrypted data into a user-provided buffer.
168  *
169  * IMPORTANT: This will abort if either #pairing_auth_init_cipher was not called
170  * or #pairing_auth_init_cipher failed.
171  *
172  * @param ctx the PairingAuthCtx instance. Will abort if null.
173  * @param inbuf the buffer containing the data to decrypt. Will abort if null.
174  * @param inlen the size of inbuf in bytes. WIll abort if 0.
175  * @param outbuf the buffer to write the decrypted data to. Will abort if null.
176  * @param outlen the size of outbuf in bytes. See #pairing_auth_safe_decrypted_size.
177  *        Will abort if 0.
178  * @return true if all the data was decrypted and written to outbuf, false
179  *         otherwise.
180  */
181 bool pairing_auth_decrypt(PairingAuthCtx* ctx, const uint8_t* inbuf, size_t inlen, uint8_t* outbuf,
182                           size_t* outlen) __INTRODUCED_IN(30);
183 
184 __END_DECLS
185