| 1 | /* |
| 2 | * QEMU crypto secret support |
| 3 | * |
| 4 | * Copyright (c) 2015 Red Hat, Inc. |
| 5 | * |
| 6 | * This library is free software; you can redistribute it and/or |
| 7 | * modify it under the terms of the GNU Lesser General Public |
| 8 | * License as published by the Free Software Foundation; either |
| 9 | * version 2.1 of the License, or (at your option) any later version. |
| 10 | * |
| 11 | * This library is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 14 | * Lesser General Public License for more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU Lesser General Public |
| 17 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. |
| 18 | * |
| 19 | */ |
| 20 | |
| 21 | #ifndef QCRYPTO_SECRET_H |
| 22 | #define QCRYPTO_SECRET_H |
| 23 | |
| 24 | #include "qapi/qapi-types-crypto.h" |
| 25 | #include "qom/object.h" |
| 26 | #include "crypto/secret_common.h" |
| 27 | |
| 28 | #define TYPE_QCRYPTO_SECRET "secret" |
| 29 | typedef struct QCryptoSecret QCryptoSecret; |
| 30 | DECLARE_INSTANCE_CHECKER(QCryptoSecret, QCRYPTO_SECRET, |
| 31 | TYPE_QCRYPTO_SECRET) |
| 32 | |
| 33 | typedef struct QCryptoSecretClass QCryptoSecretClass; |
| 34 | |
| 35 | /** |
| 36 | * QCryptoSecret: |
| 37 | * |
| 38 | * The QCryptoSecret object provides storage of secrets, |
| 39 | * which may be user passwords, encryption keys or any |
| 40 | * other kind of sensitive data that is represented as |
| 41 | * a sequence of bytes. |
| 42 | * |
| 43 | * The sensitive data associated with the secret can |
| 44 | * be provided directly via the 'data' property, or |
| 45 | * indirectly via the 'file' property. In the latter |
| 46 | * case there is support for file descriptor passing |
| 47 | * via the usual /dev/fdset/NN syntax that QEMU uses. |
| 48 | * |
| 49 | * The data for a secret can be provided in two formats, |
| 50 | * either as a UTF-8 string (the default), or as base64 |
| 51 | * encoded 8-bit binary data. The latter is appropriate |
| 52 | * for raw encryption keys, while the former is appropriate |
| 53 | * for user entered passwords. |
| 54 | * |
| 55 | * The data may be optionally encrypted with AES-256-CBC, |
| 56 | * and the decryption key provided by another |
| 57 | * QCryptoSecret instance identified by the 'keyid' |
| 58 | * property. When passing sensitive data directly |
| 59 | * via the 'data' property it is strongly recommended |
| 60 | * to use the AES encryption facility to prevent the |
| 61 | * sensitive data being exposed in the process listing |
| 62 | * or system log files. |
| 63 | * |
| 64 | * Providing data directly, insecurely (suitable for |
| 65 | * ad hoc developer testing only) |
| 66 | * |
| 67 | * $QEMU -object secret,id=sec0,data=letmein |
| 68 | * |
| 69 | * Providing data indirectly: |
| 70 | * |
| 71 | * # printf "letmein" > password.txt |
| 72 | * # $QEMU \ |
| 73 | * -object secret,id=sec0,file=password.txt |
| 74 | * |
| 75 | * Using a master encryption key with data. |
| 76 | * |
| 77 | * The master key needs to be created as 32 secure |
| 78 | * random bytes (optionally base64 encoded) |
| 79 | * |
| 80 | * # openssl rand -base64 32 > key.b64 |
| 81 | * # KEY=$(base64 -d key.b64 | hexdump -v -e '/1 "%02X"') |
| 82 | * |
| 83 | * Each secret to be encrypted needs to have a random |
| 84 | * initialization vector generated. These do not need |
| 85 | * to be kept secret |
| 86 | * |
| 87 | * # openssl rand -base64 16 > iv.b64 |
| 88 | * # IV=$(base64 -d iv.b64 | hexdump -v -e '/1 "%02X"') |
| 89 | * |
| 90 | * A secret to be defined can now be encrypted |
| 91 | * |
| 92 | * # SECRET=$(printf "letmein" | |
| 93 | * openssl enc -aes-256-cbc -a -K $KEY -iv $IV) |
| 94 | * |
| 95 | * When launching QEMU, create a master secret pointing |
| 96 | * to key.b64 and specify that to be used to decrypt |
| 97 | * the user password |
| 98 | * |
| 99 | * # $QEMU \ |
| 100 | * -object secret,id=secmaster0,format=base64,file=key.b64 \ |
| 101 | * -object secret,id=sec0,keyid=secmaster0,format=base64,\ |
| 102 | * data=$SECRET,iv=$(<iv.b64) |
| 103 | * |
| 104 | * When encrypting, the data can still be provided via an |
| 105 | * external file, in which case it is possible to use either |
| 106 | * raw binary data, or base64 encoded. This example uses |
| 107 | * raw format |
| 108 | * |
| 109 | * # printf "letmein" | |
| 110 | * openssl enc -aes-256-cbc -K $KEY -iv $IV -o pw.aes |
| 111 | * # $QEMU \ |
| 112 | * -object secret,id=secmaster0,format=base64,file=key.b64 \ |
| 113 | * -object secret,id=sec0,keyid=secmaster0,\ |
| 114 | * file=pw.aes,iv=$(<iv.b64) |
| 115 | * |
| 116 | * Note that the ciphertext can be in either raw or base64 |
| 117 | * format, as indicated by the 'format' parameter, but the |
| 118 | * plaintext resulting from decryption is expected to always |
| 119 | * be in raw format. |
| 120 | */ |
| 121 | |
| 122 | struct QCryptoSecret { |
| 123 | QCryptoSecretCommon parent_obj; |
| 124 | char *data; |
| 125 | char *file; |
| 126 | }; |
| 127 | |
| 128 | |
| 129 | struct QCryptoSecretClass { |
| 130 | QCryptoSecretCommonClass parent_class; |
| 131 | }; |
| 132 | |
| 133 | #endif /* QCRYPTO_SECRET_H */ |