1/*
2 * Copyright 2020 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Niels Sascha Reedijk, niels.reedijk@gmail.com
7 */
8
9/*!
10	\page app_keystore Password and Key Storage API
11
12	Haiku R1 introduces the first version of a system-wide key store service,
13	allows you as developer to outsource some of the credential and certificate
14	management, as well as providing an infrastructure that enables sharing
15	these artifacts between applications.
16
17	\warning The implementation in Haiku R1 is limited and is a promise of more
18		to come. Functionality beyond storing and sharing passwords is for the
19		future. Also please read the security section of this document,
20		especially when you are working with artifacts that are more sensitive.
21		In many cases you will find that this system service will work just as
22		well as making your own implementation, but there are instances in
23		which you may chose not to use it.
24
25	\section app_keystore_overview 1. Highlevel Overview (components)
26
27	The implementation is based around the following concepts:
28	 - The \b keystore is the centralized repository for your keys. It is
29	   managed by the \b keystore_server and it contains one or more
30	   \b keyrings.
31	 - A \b keyring is a collection of keys. There is always a
32	   \b master \b keyring, which cannot be removed. Access is organized
33	   around keyrings. From a user's perspective, when an application wants
34	   to access keys in a keyring, the user will have to grant permission to
35	   that application to access the keyring. A keyring is identified by a
36	   name, which needs to be unique on the user's system.
37	 - A keyring contains \b keys. These are the smallest unit in the system.
38	   A key can be anything that you want to safeguard in the keystore. Keys
39	   are identified by the combination of an identifier and a secondary
40	   identifier. These should be unique within a keyring.
41	 - The final piece is the concept of \b permissions. In the current
42	   implementation, an application needs to ask permission to access a
43	   keyring. The \c keystore_server will validate the permissions, and if
44	   necessary prompt the user to grant one-time or a permant access. If the
45	   user only allows it once, access is granted until the application
46	   terminates.
47
48	As a user of the API, you will mostly be working with \ref BKeyStore, as
49	the access point that queries and modifies keyrings and keys. An individual
50	key is represented by the \ref BKey object.
51
52	\section app_keystore_security 2. Security
53
54	The current implementation of this API should be considered low-security.
55	The most important thing to know is that there is \b no \b encryption
56	applied when storing the keys and keyrings to the drive. This means that
57	the data can be read by any malicious actor that can access the drive of
58	your machine.
59
60	This should also puts the current locking mechanism in perspective. While
61	the \c keystore_server will prompt the user to grant (or deny) access to
62	your application, when it wants to access a keyring, this again does not
63	prevent any malicious actor to bypass the \c keystore_server and directly
64	read from (and write to!) the file.
65
66	When considering on whether to use the current API, there are a few things
67	to think about:
68	 - First, consider whether you should store the keys at all. Passwords to
69	   services with extremely sensitive personal or financial information,
70	   such as email passwords or credentials to financial institutions, should
71	   not be stored at all. Prompt your user for the credentials when needed,
72	   and don't keep them for later use.
73	 - Secondly, if you are storing credentials for use with web services,
74	   check if the service you are using supports using access tokens. Many
75	   APIs have them, and often use it in combination with some form of
76	   permission system or scoping, making it possible for you to keep access
77	   as limited as possible. Furthermore, the user often has the ability to
78	   revoke access to a token, in case they think it is compromised.
79	 - When you assess that you really do need to store the credentials, make
80	   a determination first about whether or not the credentials should have
81	   some form of encryption. For now you should consider looking for another
82	   solution to storing sensitive data, but contributions to improve this
83	   API are very welcome. It is beyond the scope of this document to discuss
84	   strategies around encryption.
85	 - When you assess the risk is low enough not to employ encryption
86	   strategies, you may consider using this API. It is particularly
87	   recommended if you will be sharing the credentials with more than one
88	   application.
89
90	\warning In the end, it is up to you as a developer to be conscious of any
91		choices you make when it comes to user data, and credentials are no
92		different. When you decide that the Password and Key API does not fit
93		your needs, choose a framework or library that does fit your purpose.
94
95	\section app_keystore_usage 3. Practical use of the API
96
97	Below are two distinct examples on how you may use the API.
98
99	\subsection app_keystore_usage_web The Langlaufer Web Browser
100
101	We are working on the infamous Langlaufer web browser, and we are adding
102	a feature where we autocomplete user names and passwords. It is decided to
103	use the Password and Key Storage API to do our key management. Whenever we
104	land on a web page with a login screen, we will try to see if we have
105	credentials for that web page. Part of the requirements is that we support
106	more than one set of credentials for a web page.
107
108	It is decided that the application will store the user credentials in it's
109	own keyring, as we do not want to interfere with any other keys in the
110	master key. Additionally, we will use both the primary and secondary
111	identifier fields. The primary will contain the hostname of the website,
112	and the secondary will contain the user name.
113
114	One final design note is that all the calls to the \c keystore_server are
115	synchronous, meaning they will block until there is a response back from
116	the keystore. In the case that a user needs to be prompted for a password,
117	the call will be blocked until they make a decision. That is why any calls
118	on \ref BKeyStore should be done on a separate worker thread, instead of
119	within the logic of a Window.
120
121	For clarity, the example below displays the interaction with the
122	\ref BKeyStore and \ref BKey classes through some utility functions. It is
123	up to the reader to put that in a separate working thread.
124
125	\code{.cpp}
126	#include <Key.h>
127	#include <KeyStore.h>
128
129	const char *kLanglauferKeyringName = "Langlaufer";
130
131	BObjectList<BPasswordKey>
132	GetKeysForWebsite(const char *baseUrl) {
133		// There may be more than one match, so we use the iteration methods.
134		BKeyStore keyStore;
135		uint32 cookie;
136		BPasswordKey currentKey;
137		BObjectList<BPasswordKey> list;
138		bool next = true;
139
140		while(next) {
141			status_t status = keyStore.GetNextKey(kLanglauferKeyringName,
142				B_KEY_TYPE_PASSWORD, B_KEY_PURPOSE_WEB, cookie, currentKey);
143			switch(status) {
144				case B_OK:
145					// Try to see if the key matches the website
146					if (currentKey.Identifier() == baseUrl) {
147						// Add the item to the list.
148						list.AddItem(new BPasswordKey(currentKey));
149					}
150					break;
151				case B_BAD_VALUE:
152					// The keyring does not exist, create it, and end the
153					// search
154					CreateKeyring();
155					next = false;
156					break;
157				default:
158					// Something else went wrong, like the user did not give
159					// authorization, or we are at the end of the list.
160					// Bail out the search at this point.
161					next = false;
162					break;
163				}
164			}
165		}
166
167		return list;
168	}
169
170	void
171	CreateKeyring() {
172		BKeyStore keyStore;
173		// Ignore the return value in the next line, it may fail but that won't
174		// interrupt the flow of our program.
175		keyStore.AddKeyring(kLanglauferKeyringName);
176	}
177
178	void
179	AddOrReplaceKey(const char *baseUrl, const char *user, const char *password) {
180		BKeyStore keyStore;
181		BPasswordKey key;
182
183		// Fill out the key with existing data, or create new data
184		if (keyStore.GetKey(kLanglauferKeyringName, B_KEY_TYPE_PASSWORD, baseUrl, user, &key) == B_OK) {
185			// Remove the existing key
186			keyStore.RemoveKey(kLanglauferKeyringName, key);
187			// Update the password
188			key.SetPassword(password);
189		} else {
190			key.SetTo(password, B_KEY_PURPOSE_WEB, user, password);
191		}
192
193		// Store the updated/new key in the keyring
194		keyStore.AddKey(kLanglauferKeyringName, key);
195	}
196	\endcode
197
198	\subsection app_keystore_usage_coolwebservice The CoolWebService Tool Suite
199
200	We are working on a set of tools that interface with a cool web service.
201	Instead of building one monolithic application, we make several small tools
202	with specific jobs for this cool web service. One of the tools does the
203	authentication, and stores the key in the master keyring on the system. The
204	other tools use this key to access the API.
205
206	Each tool requires the authentication token to be set up properly. That's
207	why in the \ref BApplication::ReadyToRun() hook we check for the
208	availability of the key. If it is not available, or it does not work, the
209	user will be redirected to the authentication tool. The key will be stored
210	as a password. It will be identified by the identifier "CoolWebService".
211
212	\code{.cpp}
213	void
214	CoolPushTool::ReadyToRun() {
215		BKeyStore keyStore;
216		BPasswordKey key;
217
218		if (keyStore.GetKey(B_KEY_TYPE_PASSWORD, "CoolWebService", key) != B_OK) {
219			// Terminate the application and re-authenticate
220			...
221		}
222
223		// Extract the key
224		BString accessToken = key.Password();
225
226		// Validate the key, and if succesful, continue
227		...
228	}
229	\endcode
230
231*/
232