/*
* QEMU crypto secret support
*
* Copyright (c) 2015 Red Hat, Inc.
*
* 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 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QCRYPTO_SECRET_H
#define QCRYPTO_SECRET_H
#include "qom/object.h"
#define TYPE_QCRYPTO_SECRET "secret"
#define QCRYPTO_SECRET(obj) \
OBJECT_CHECK(QCryptoSecret, (obj), TYPE_QCRYPTO_SECRET)
typedef struct QCryptoSecret QCryptoSecret;
typedef struct QCryptoSecretClass QCryptoSecretClass;
/**
* QCryptoSecret:
*
* The QCryptoSecret object provides storage of secrets,
* which may be user passwords, encryption keys or any
* other kind of sensitive data that is represented as
* a sequence of bytes.
*
* The sensitive data associated with the secret can
* be provided directly via the 'data' property, or
* indirectly via the 'file' property. In the latter
* case there is support for file descriptor passing
* via the usual /dev/fdset/NN syntax that QEMU uses.
*
* The data for a secret can be provided in two formats,
* either as a UTF-8 string (the default), or as base64
* encoded 8-bit binary data. The latter is appropriate
* for raw encryption keys, while the former is appropriate
* for user entered passwords.
*
* The data may be optionally encrypted with AES-256-CBC,
* and the decryption key provided by another
* QCryptoSecret instance identified by the 'keyid'
* property. When passing sensitive data directly
* via the 'data' property it is strongly recommended
* to use the AES encryption facility to prevent the
* sensitive data being exposed in the process listing
* or system log files.
*
* Providing data directly, insecurely (suitable for
* ad hoc developer testing only)
*
* $QEMU -object secret,id=sec0,data=letmein
*
* Providing data indirectly:
*
* # printf "letmein" > password.txt
* # $QEMU \
* -object secret,id=sec0,file=password.txt
*
* Using a master encryption key with data.
*
* The master key needs to be created as 32 secure
* random bytes (optionally base64 encoded)
*
* # openssl rand -base64 32 > key.b64
* # KEY=$(base64 -d key.b64 | hexdump -v -e '/1 "%02X"')
*
* Each secret to be encrypted needs to have a random
* initialization vector generated. These do not need
* to be kept secret
*
* # openssl rand -base64 16 > iv.b64
* # IV=$(base64 -d iv.b64 | hexdump -v -e '/1 "%02X"')
*
* A secret to be defined can now be encrypted
*
* # SECRET=$(printf "letmein" |
* openssl enc -aes-256-cbc -a -K $KEY -iv $IV)
*
* When launching QEMU, create a master secret pointing
* to key.b64 and specify that to be used to decrypt
* the user password
*
* # $QEMU \
* -object secret,id=secmaster0,format=base64,file=key.b64 \
* -object secret,id=sec0,keyid=secmaster0,format=base64,\
* data=$SECRET,iv=$(<iv.b64)
*
* When encrypting, the data can still be provided via an
* external file, in which case it is possible to use either
* raw binary data, or base64 encoded. This example uses
* raw format
*
* # printf "letmein" |
* openssl enc -aes-256-cbc -K $KEY -iv $IV -o pw.aes
* # $QEMU \
* -object secret,id=secmaster0,format=base64,file=key.b64 \
* -object secret,id=sec0,keyid=secmaster0,\
* file=pw.aes,iv=$(<iv.b64)
*
* Note that the ciphertext can be in either raw or base64
* format, as indicated by the 'format' parameter, but the
* plaintext resulting from decryption is expected to always
* be in raw format.
*/
struct QCryptoSecret {
Object parent_obj;
uint8_t *rawdata;
size_t rawlen;
QCryptoSecretFormat format;
char *data;
char *file;
char *keyid;
char *iv;
};
struct QCryptoSecretClass {
ObjectClass parent_class;
};
extern int qcrypto_secret_lookup(const char *secretid,
uint8_t **data,
size_t *datalen,
Error **errp);
extern char *qcrypto_secret_lookup_as_utf8(const char *secretid,
Error **errp);
extern char *qcrypto_secret_lookup_as_base64(const char *secretid,
Error **errp);
#endif /* QCRYPTO_SECRET_H */