3
0
mirror of https://git.kernel.org/pub/scm/network/wireless/iwd.git synced 2024-12-23 06:02:37 +01:00
iwd/src/storage.h
James Prestwood 01cd858760 storage: implement network profile encryption
Some users don't like the idea of storing network credentials in
plaintext on the file system.  This patch implements an option to
encrypt such profiles using a secret key.  The origin of the key can in
theory be anything, but would typically be provided by systemd via
'LoadEncryptedCredential' setting in the iwd unit file.

The encryption operates on the entire [Security] group as well as all
embedded groups. Once encrypted the [Security] group will be replaced
with two key/values:

EncryptedSalt - A random string of bytes used for the encryption
EncryptedSecurity - A string of bytes containing the encrypted
                    [Security] group, as well as all embedded groups.

After the profile has been encrypted these values should not be
modified.  Note that any values added to [Security] after encryption
has no effect.  Once the profile is encrypted there is no way to modify
[Security] without manually decrypting first, or just re-creating it
entirely which effectively treated a 'new' profile.

The encryption/decryption is done using AES-SIV with a salt value and
the network SSID as the IV.

Once a key is set any profiles opened will automatically be encrypted
and re-written to disk.  Modules using network_storage_open will be
provided the decrypted profile, and will be unaware it was ever
encrypted in the first place.  Similarly when network_storage_sync is
called the profile will by automatically encrypted and written to disk
without the caller needing to do anything special.

A few private storage.c helpers were added to serve several purposes:

storage_init/exit():
This sets/cleans up the encryption key direct from systemd then uses
extract and expand to create a new fixed length key to perform
encryption/decryption.

__storage_decrypt():
Low level API to decrypt an l_settings object using a previously set
key and the SSID/name for the network.  This returns a 'changed' out
parameter signifying that the settings need to be encrypted and
re-written to disk.  The purpose of exposing this is for a standalone
decryption tool which does not re-write any settings.

storage_decrypt():
Wrapper around __storage_decrypt() that handles re-writing a new
profile to disk. This was exposed in order to support hotspot profiles.

__storage_encrypt():
Encrypts an l_settings object and returns the full profile as data
2022-02-15 17:19:33 -06:00

63 lines
2.3 KiB
C

/*
*
* Wireless daemon for Linux
*
* Copyright (C) 2013-2019 Intel Corporation. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <time.h>
struct l_settings;
enum security;
ssize_t read_file(void *buffer, size_t len, const char *path_fmt, ...)
__attribute__((format(printf, 3, 4)));
ssize_t write_file(const void *buffer, size_t len, bool preserve_times,
const char *path_fmt, ...)
__attribute__((format(printf, 4, 5)));
bool storage_is_file(const char *filename);
bool storage_create_dirs(void);
void storage_cleanup_dirs(void);
char *storage_get_path(const char *format, ...);
char *storage_get_hotspot_path(const char *format, ...);
const char *storage_network_ssid_from_path(const char *path,
enum security *type);
char *storage_get_network_file_path(enum security type, const char *ssid);
struct l_settings *storage_network_open(enum security type, const char *ssid);
int storage_network_touch(enum security type, const char *ssid);
void storage_network_sync(enum security type, const char *ssid,
struct l_settings *settings);
int storage_network_remove(enum security type, const char *ssid);
struct l_settings *storage_known_frequencies_load(void);
void storage_known_frequencies_sync(struct l_settings *known_freqs);
int __storage_decrypt(struct l_settings *settings, const char *ssid,
bool *changed);
char *__storage_encrypt(const struct l_settings *settings, const char *ssid,
size_t *out_len);
bool storage_decrypt(struct l_settings *settings, const char *path,
const char *name);
bool storage_init(const uint8_t *key, size_t key_len);
void storage_exit(void);