Import QEMU upstream snapshot d2e570c

Upstream: https://gitlab.com/qemu-project/qemu.git

Upstream-Commit: d2e570cc0f97b936902a5b1b86b73c0f5998b475
This commit is contained in:
Yaya48 committed 2026-08-31 02:15:30 +02:00
commit cf256aa081
11315 files changed
+3598369

No files matched your search

+164
View File
@@ -0,0 +1,164 @@
/*
* AES round fragments, generic version
* SPDX-License-Identifier: GPL-2.0-or-later
*
* Copyright (C) 2023 Linaro, Ltd.
*/
#ifndef CRYPTO_AES_ROUND_H
#define CRYPTO_AES_ROUND_H
/* Hosts with acceleration will usually need a 16-byte vector type. */
typedef uint8_t AESStateVec __attribute__((vector_size(16)));
typedef union {
uint8_t b[16];
uint32_t w[4];
uint64_t d[2];
AESStateVec v;
} AESState;
#include "host/crypto/aes-round.h"
/*
* Perform MixColumns.
*/
void aesenc_MC_gen(AESState *ret, const AESState *st);
void aesenc_MC_genrev(AESState *ret, const AESState *st);
static inline void aesenc_MC(AESState *r, const AESState *st, bool be)
{
if (HAVE_AES_ACCEL) {
aesenc_MC_accel(r, st, be);
} else if (HOST_BIG_ENDIAN == be) {
aesenc_MC_gen(r, st);
} else {
aesenc_MC_genrev(r, st);
}
}
/*
* Perform SubBytes + ShiftRows + AddRoundKey.
*/
void aesenc_SB_SR_AK_gen(AESState *ret, const AESState *st,
const AESState *rk);
void aesenc_SB_SR_AK_genrev(AESState *ret, const AESState *st,
const AESState *rk);
static inline void aesenc_SB_SR_AK(AESState *r, const AESState *st,
const AESState *rk, bool be)
{
if (HAVE_AES_ACCEL) {
aesenc_SB_SR_AK_accel(r, st, rk, be);
} else if (HOST_BIG_ENDIAN == be) {
aesenc_SB_SR_AK_gen(r, st, rk);
} else {
aesenc_SB_SR_AK_genrev(r, st, rk);
}
}
/*
* Perform SubBytes + ShiftRows + MixColumns + AddRoundKey.
*/
void aesenc_SB_SR_MC_AK_gen(AESState *ret, const AESState *st,
const AESState *rk);
void aesenc_SB_SR_MC_AK_genrev(AESState *ret, const AESState *st,
const AESState *rk);
static inline void aesenc_SB_SR_MC_AK(AESState *r, const AESState *st,
const AESState *rk, bool be)
{
if (HAVE_AES_ACCEL) {
aesenc_SB_SR_MC_AK_accel(r, st, rk, be);
} else if (HOST_BIG_ENDIAN == be) {
aesenc_SB_SR_MC_AK_gen(r, st, rk);
} else {
aesenc_SB_SR_MC_AK_genrev(r, st, rk);
}
}
/*
* Perform InvMixColumns.
*/
void aesdec_IMC_gen(AESState *ret, const AESState *st);
void aesdec_IMC_genrev(AESState *ret, const AESState *st);
static inline void aesdec_IMC(AESState *r, const AESState *st, bool be)
{
if (HAVE_AES_ACCEL) {
aesdec_IMC_accel(r, st, be);
} else if (HOST_BIG_ENDIAN == be) {
aesdec_IMC_gen(r, st);
} else {
aesdec_IMC_genrev(r, st);
}
}
/*
* Perform InvSubBytes + InvShiftRows + AddRoundKey.
*/
void aesdec_ISB_ISR_AK_gen(AESState *ret, const AESState *st,
const AESState *rk);
void aesdec_ISB_ISR_AK_genrev(AESState *ret, const AESState *st,
const AESState *rk);
static inline void aesdec_ISB_ISR_AK(AESState *r, const AESState *st,
const AESState *rk, bool be)
{
if (HAVE_AES_ACCEL) {
aesdec_ISB_ISR_AK_accel(r, st, rk, be);
} else if (HOST_BIG_ENDIAN == be) {
aesdec_ISB_ISR_AK_gen(r, st, rk);
} else {
aesdec_ISB_ISR_AK_genrev(r, st, rk);
}
}
/*
* Perform InvSubBytes + InvShiftRows + AddRoundKey + InvMixColumns.
*/
void aesdec_ISB_ISR_AK_IMC_gen(AESState *ret, const AESState *st,
const AESState *rk);
void aesdec_ISB_ISR_AK_IMC_genrev(AESState *ret, const AESState *st,
const AESState *rk);
static inline void aesdec_ISB_ISR_AK_IMC(AESState *r, const AESState *st,
const AESState *rk, bool be)
{
if (HAVE_AES_ACCEL) {
aesdec_ISB_ISR_AK_IMC_accel(r, st, rk, be);
} else if (HOST_BIG_ENDIAN == be) {
aesdec_ISB_ISR_AK_IMC_gen(r, st, rk);
} else {
aesdec_ISB_ISR_AK_IMC_genrev(r, st, rk);
}
}
/*
* Perform InvSubBytes + InvShiftRows + InvMixColumns + AddRoundKey.
*/
void aesdec_ISB_ISR_IMC_AK_gen(AESState *ret, const AESState *st,
const AESState *rk);
void aesdec_ISB_ISR_IMC_AK_genrev(AESState *ret, const AESState *st,
const AESState *rk);
static inline void aesdec_ISB_ISR_IMC_AK(AESState *r, const AESState *st,
const AESState *rk, bool be)
{
if (HAVE_AES_ACCEL) {
aesdec_ISB_ISR_IMC_AK_accel(r, st, rk, be);
} else if (HOST_BIG_ENDIAN == be) {
aesdec_ISB_ISR_IMC_AK_gen(r, st, rk);
} else {
aesdec_ISB_ISR_IMC_AK_genrev(r, st, rk);
}
}
#endif /* CRYPTO_AES_ROUND_H */
+40
View File
@@ -0,0 +1,40 @@
#ifndef QEMU_AES_H
#define QEMU_AES_H
#define AES_MAXNR 14
#define AES_BLOCK_SIZE 16
struct aes_key_st {
uint32_t rd_key[4 *(AES_MAXNR + 1)];
int rounds;
};
typedef struct aes_key_st AES_KEY;
/* FreeBSD/OpenSSL have their own AES functions with the same names in -lcrypto
* (which might be pulled in via curl), so redefine to avoid conflicts. */
#define AES_set_encrypt_key QEMU_AES_set_encrypt_key
#define AES_set_decrypt_key QEMU_AES_set_decrypt_key
#define AES_encrypt QEMU_AES_encrypt
#define AES_decrypt QEMU_AES_decrypt
int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
void AES_encrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
void AES_decrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
extern const uint8_t AES_sbox[256];
extern const uint8_t AES_isbox[256];
/*
AES_Te0[x] = S [x].[02, 01, 01, 03];
AES_Td0[x] = Si[x].[0e, 09, 0d, 0b];
*/
extern const uint32_t AES_Te0[256], AES_Td0[256];
#endif
+134
View File
@@ -0,0 +1,134 @@
/*
* QEMU Crypto anti forensic information splitter
*
* Copyright (c) 2015-2016 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef QCRYPTO_AFSPLIT_H
#define QCRYPTO_AFSPLIT_H
#include "crypto/hash.h"
/**
* This module implements the anti-forensic splitter that is specified
* as part of the LUKS format:
*
* http://clemens.endorphin.org/cryptography
* http://clemens.endorphin.org/TKS1-draft.pdf
*
* The core idea is to take a short piece of data (key material)
* and process it to expand it to a much larger piece of data.
* The expansion process is reversible, to obtain the original
* short data. The key property of the expansion is that if any
* byte in the larger data set is changed / missing, it should be
* impossible to recreate the original short data.
*
* <example>
* <title>Creating a large split key for storage</title>
* <programlisting>
* size_t nkey = 32;
* uint32_t stripes = 32768; // To produce a 1 MB split key
* uint8_t *masterkey = ....a 32-byte AES key...
* uint8_t *splitkey;
*
* splitkey = g_new0(uint8_t, nkey * stripes);
*
* if (qcrypto_afsplit_encode(QCRYPTO_HASH_ALGO_SHA256,
* nkey, stripes,
* masterkey, splitkey, errp) < 0) {
* g_free(splitkey);
* g_free(masterkey);
* return -1;
* }
*
* ...store splitkey somewhere...
*
* g_free(splitkey);
* g_free(masterkey);
* </programlisting>
* </example>
*
* <example>
* <title>Retrieving a master key from storage</title>
* <programlisting>
* size_t nkey = 32;
* uint32_t stripes = 32768; // To produce a 1 MB split key
* uint8_t *masterkey;
* uint8_t *splitkey = .... read in 1 MB of data...
*
* masterkey = g_new0(uint8_t, nkey);
*
* if (qcrypto_afsplit_decode(QCRYPTO_HASH_ALGO_SHA256,
* nkey, stripes,
* splitkey, masterkey, errp) < 0) {
* g_free(splitkey);
* g_free(masterkey);
* return -1;
* }
*
* ..decrypt data with masterkey...
*
* g_free(splitkey);
* g_free(masterkey);
* </programlisting>
* </example>
*/
/**
* qcrypto_afsplit_encode:
* @hash: the hash algorithm to use for data expansion
* @blocklen: the size of @in in bytes
* @stripes: the number of times to expand @in in size
* @in: the master key to be expanded in size
* @out: preallocated buffer to hold the split key
* @errp: pointer to a NULL-initialized error object
*
* Split the data in @in, which is @blocklen bytes in
* size, to form a larger piece of data @out, which is
* @blocklen * @stripes bytes in size.
*
* Returns: 0 on success, -1 on error;
*/
int qcrypto_afsplit_encode(QCryptoHashAlgo hash,
size_t blocklen,
uint32_t stripes,
const uint8_t *in,
uint8_t *out,
Error **errp);
/**
* qcrypto_afsplit_decode:
* @hash: the hash algorithm to use for data compression
* @blocklen: the size of @out in bytes
* @stripes: the number of times to decrease @in in size
* @in: the split key to be recombined
* @out: preallocated buffer to hold the master key
* @errp: pointer to a NULL-initialized error object
*
* Join the data in @in, which is @blocklen * @stripes
* bytes in size, to form the original small piece of
* data @out, which is @blocklen bytes in size.
*
* Returns: 0 on success, -1 on error;
*/
int qcrypto_afsplit_decode(QCryptoHashAlgo hash,
size_t blocklen,
uint32_t stripes,
const uint8_t *in,
uint8_t *out,
Error **errp);
#endif /* QCRYPTO_AFSPLIT_H */
+179
View File
@@ -0,0 +1,179 @@
/*
* QEMU Crypto asymmetric algorithms
*
* Copyright (c) 2022 Bytedance
* Author: zhenwei pi <[email protected]>
*
* 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QCRYPTO_AKCIPHER_H
#define QCRYPTO_AKCIPHER_H
#include "qapi/qapi-types-crypto.h"
typedef struct QCryptoAkCipher QCryptoAkCipher;
/**
* qcrypto_akcipher_supports:
* @opts: the asymmetric key algorithm and related options
*
* Determine if asymmetric key cipher described with @opts is
* supported by the current configured build
*
* Returns: true if it is supported, false otherwise.
*/
bool qcrypto_akcipher_supports(QCryptoAkCipherOptions *opts);
/**
* qcrypto_akcipher_new:
* @opts: specify the algorithm and the related arguments
* @type: private or public key type
* @key: buffer to store the key
* @key_len: the length of key buffer
* @errp: error pointer
*
* Create akcipher context
*
* Returns: On success, a new QCryptoAkCipher initialized with @opt
* is created and returned, otherwise NULL is returned.
*/
QCryptoAkCipher *qcrypto_akcipher_new(const QCryptoAkCipherOptions *opts,
QCryptoAkCipherKeyType type,
const uint8_t *key, size_t key_len,
Error **errp);
/**
* qcrypto_akcipher_encrypt:
* @akcipher: akcipher context
* @in: plaintext pending to be encrypted
* @in_len: length of plaintext, less or equal to the size reported
* by a call to qcrypto_akcipher_max_plaintext_len()
* @out: buffer to store the ciphertext
* @out_len: length of ciphertext, less or equal to the size reported
* by a call to qcrypto_akcipher_max_ciphertext_len()
* @errp: error pointer
*
* Encrypt @in and write ciphertext into @out
*
* Returns: length of ciphertext if encrypt succeed,
* otherwise -1 is returned
*/
int qcrypto_akcipher_encrypt(QCryptoAkCipher *akcipher,
const void *in, size_t in_len,
void *out, size_t out_len, Error **errp);
/**
* qcrypto_akcipher_decrypt:
* @akcipher: akcipher context
* @in: ciphertext to be decrypted
* @in_len: the length of ciphertext, less or equal to the size reported
* by a call to qcrypto_akcipher_max_ciphertext_len()
* @out: buffer to store the plaintext
* @out_len: length of the plaintext buffer, less or equal to the size
* reported by a call to qcrypto_akcipher_max_plaintext_len()
* @errp: error pointer
*
* Decrypt @in and write plaintext into @out
*
* Returns: length of plaintext if decrypt succeed,
* otherwise -1 is returned
*/
int qcrypto_akcipher_decrypt(QCryptoAkCipher *akcipher,
const void *in, size_t in_len,
void *out, size_t out_len, Error **errp);
/**
* qcrypto_akcipher_sign:
* @akcipher: akcipher context
* @in: data to be signed
* @in_len: the length of data, less or equal to the size reported
* by a call to qcrypto_akcipher_max_dgst_len()
* @out: buffer to store the signature
* @out_len: length of the signature buffer, less or equal to the size
* by a call to qcrypto_akcipher_max_signature_len()
* @errp: error pointer
*
* Generate signature for @in, write into @out
*
* Returns: length of signature if succeed,
* otherwise -1 is returned
*/
int qcrypto_akcipher_sign(QCryptoAkCipher *akcipher,
const void *in, size_t in_len,
void *out, size_t out_len, Error **errp);
/**
* qcrypto_akcipher_verify:
* @akcipher: akcipher context
* @in: pointer to the signature
* @in_len: length of signature, ess or equal to the size reported
* by a call to qcrypto_akcipher_max_signature_len()
* @in2: pointer to original data
* @in2_len: the length of original data, less or equal to the size
* by a call to qcrypto_akcipher_max_dgst_len()
* @errp: error pointer
*
* Verify @in and @in2 match or not
*
* Returns: 0 for succeed,
* otherwise -1 is returned
*/
int qcrypto_akcipher_verify(QCryptoAkCipher *akcipher,
const void *in, size_t in_len,
const void *in2, size_t in2_len, Error **errp);
int qcrypto_akcipher_max_plaintext_len(QCryptoAkCipher *akcipher);
int qcrypto_akcipher_max_ciphertext_len(QCryptoAkCipher *akcipher);
int qcrypto_akcipher_max_signature_len(QCryptoAkCipher *akcipher);
int qcrypto_akcipher_max_dgst_len(QCryptoAkCipher *akcipher);
/**
* qcrypto_akcipher_free:
* @akcipher: akcipher context
*
* Free the akcipher context
*
*/
void qcrypto_akcipher_free(QCryptoAkCipher *akcipher);
/**
* qcrypto_akcipher_export_p8info:
* @opts: the options of the akcipher to be exported.
* @key: the original key of the akcipher to be exported.
* @keylen: length of the 'key'
* @dst: output parameter, if export succeed, *dst is set to the
* PKCS#8 encoded private key, caller MUST free this key with
* g_free after use.
* @dst_len: output parameter, indicates the length of PKCS#8 encoded
* key.
*
* Export the akcipher into DER encoded pkcs#8 private key info, expects
* |key| stores a valid asymmetric PRIVATE key.
*
* Returns: 0 for succeed, otherwise -1 is returned.
*/
int qcrypto_akcipher_export_p8info(const QCryptoAkCipherOptions *opts,
uint8_t *key, size_t keylen,
uint8_t **dst, size_t *dst_len,
Error **errp);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoAkCipher, qcrypto_akcipher_free)
#endif /* QCRYPTO_AKCIPHER_H */
+329
View File
@@ -0,0 +1,329 @@
/*
* QEMU Crypto block device encryption
*
* Copyright (c) 2015-2016 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.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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QCRYPTO_BLOCK_H
#define QCRYPTO_BLOCK_H
#include "crypto/cipher.h"
#include "crypto/ivgen.h"
typedef struct QCryptoBlock QCryptoBlock;
/* See also QCryptoBlockFormat, QCryptoBlockCreateOptions
* and QCryptoBlockOpenOptions in qapi/crypto.json */
typedef int (*QCryptoBlockReadFunc)(QCryptoBlock *block,
size_t offset,
uint8_t *buf,
size_t buflen,
void *opaque,
Error **errp);
typedef int (*QCryptoBlockInitFunc)(QCryptoBlock *block,
size_t headerlen,
void *opaque,
Error **errp);
typedef int (*QCryptoBlockWriteFunc)(QCryptoBlock *block,
size_t offset,
const uint8_t *buf,
size_t buflen,
void *opaque,
Error **errp);
/**
* qcrypto_block_has_format:
* @format: the encryption format
* @buf: the data from head of the volume
* @len: the length of @buf in bytes
*
* Given @len bytes of data from the head of a storage volume
* in @buf, probe to determine if the volume has the encryption
* format specified in @format.
*
* Returns: true if the data in @buf matches @format
*/
bool qcrypto_block_has_format(QCryptoBlockFormat format,
const uint8_t *buf,
size_t buflen);
typedef enum {
QCRYPTO_BLOCK_OPEN_NO_IO = (1 << 0),
QCRYPTO_BLOCK_OPEN_DETACHED = (1 << 1),
} QCryptoBlockOpenFlags;
/**
* qcrypto_block_open:
* @options: the encryption options
* @optprefix: name prefix for options
* @readfunc: callback for reading data from the volume
* @opaque: data to pass to @readfunc
* @flags: bitmask of QCryptoBlockOpenFlags values
* @errp: pointer to a NULL-initialized error object
*
* Create a new block encryption object for an existing
* storage volume encrypted with format identified by
* the parameters in @options.
*
* This will use @readfunc to initialize the encryption
* context based on the volume header(s), extracting the
* master key(s) as required.
*
* If @flags contains QCRYPTO_BLOCK_OPEN_NO_IO then
* the open process will be optimized to skip any parts
* that are only required to perform I/O. In particular
* this would usually avoid the need to decrypt any
* master keys. The only thing that can be done with
* the resulting QCryptoBlock object would be to query
* metadata such as the payload offset. There will be
* no cipher or ivgen objects available.
*
* If @flags contains QCRYPTO_BLOCK_OPEN_DETACHED then
* the open process will be optimized to skip the LUKS
* payload overlap check.
*
* If any part of initializing the encryption context
* fails an error will be returned. This could be due
* to the volume being in the wrong format, a cipher
* or IV generator algorithm that is not supported,
* or incorrect passphrases.
*
* Returns: a block encryption format, or NULL on error
*/
QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
const char *optprefix,
QCryptoBlockReadFunc readfunc,
void *opaque,
unsigned int flags,
Error **errp);
typedef enum {
QCRYPTO_BLOCK_CREATE_DETACHED = (1 << 0),
} QCryptoBlockCreateFlags;
/**
* qcrypto_block_create:
* @options: the encryption options
* @optprefix: name prefix for options
* @initfunc: callback for initializing volume header
* @writefunc: callback for writing data to the volume header
* @opaque: data to pass to @initfunc and @writefunc
* @flags: bitmask of QCryptoBlockCreateFlags values
* @errp: pointer to a NULL-initialized error object
*
* Create a new block encryption object for initializing
* a storage volume to be encrypted with format identified
* by the parameters in @options.
*
* This method will allocate space for a new volume header
* using @initfunc and then write header data using @writefunc,
* generating new master keys, etc as required. Any existing
* data present on the volume will be irrevocably destroyed.
*
* If @flags contains QCRYPTO_BLOCK_CREATE_DETACHED then
* the open process will set the payload_offset_sector to 0
* to specify the starting point for the read/write of a
* detached LUKS header image.
*
* If any part of initializing the encryption context
* fails an error will be returned. This could be due
* to the volume being in the wrong format, a cipher
* or IV generator algorithm that is not supported,
* or incorrect passphrases.
*
* Returns: a block encryption format, or NULL on error
*/
QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
const char *optprefix,
QCryptoBlockInitFunc initfunc,
QCryptoBlockWriteFunc writefunc,
void *opaque,
unsigned int flags,
Error **errp);
/**
* qcrypto_block_amend_options:
* @block: the block encryption object
*
* @readfunc: callback for reading data from the volume header
* @writefunc: callback for writing data to the volume header
* @opaque: data to pass to @readfunc and @writefunc
* @options: the new/amended encryption options
* @force: hint for the driver to allow unsafe operation
* @errp: error pointer
*
* Changes the crypto options of the encryption format
*
*/
int qcrypto_block_amend_options(QCryptoBlock *block,
QCryptoBlockReadFunc readfunc,
QCryptoBlockWriteFunc writefunc,
void *opaque,
QCryptoBlockAmendOptions *options,
bool force,
Error **errp);
/**
* qcrypto_block_calculate_payload_offset:
* @create_opts: the encryption options
* @optprefix: name prefix for options
* @len: output for number of header bytes before payload
* @errp: pointer to a NULL-initialized error object
*
* Calculate the number of header bytes before the payload in an encrypted
* storage volume. The header is an area before the payload that is reserved
* for encryption metadata.
*
* Returns: true on success, false on error
*/
bool
qcrypto_block_calculate_payload_offset(QCryptoBlockCreateOptions *create_opts,
const char *optprefix,
size_t *len,
Error **errp);
/**
* qcrypto_block_get_info:
* @block: the block encryption object
* @errp: pointer to a NULL-initialized error object
*
* Get information about the configuration options for the
* block encryption object. This includes details such as
* the cipher algorithms, modes, and initialization vector
* generators.
*
* Returns: a block encryption info object, or NULL on error
*/
QCryptoBlockInfo *qcrypto_block_get_info(QCryptoBlock *block,
Error **errp);
/**
* @qcrypto_block_decrypt:
* @block: the block encryption object
* @offset: the position at which @iov was read
* @buf: the buffer to decrypt
* @len: the length of @buf in bytes
* @errp: pointer to a NULL-initialized error object
*
* Decrypt @len bytes of cipher text in @buf, writing
* plain text back into @buf. @len and @offset must be
* a multiple of the encryption format sector size.
*
* Returns 0 on success, -1 on failure
*/
int qcrypto_block_decrypt(QCryptoBlock *block,
uint64_t offset,
uint8_t *buf,
size_t len,
Error **errp);
/**
* @qcrypto_block_encrypt:
* @block: the block encryption object
* @offset: the position at which @iov will be written
* @buf: the buffer to decrypt
* @len: the length of @buf in bytes
* @errp: pointer to a NULL-initialized error object
*
* Encrypt @len bytes of plain text in @buf, writing
* cipher text back into @buf. @len and @offset must be
* a multiple of the encryption format sector size.
*
* Returns 0 on success, -1 on failure
*/
int qcrypto_block_encrypt(QCryptoBlock *block,
uint64_t offset,
uint8_t *buf,
size_t len,
Error **errp);
/**
* qcrypto_block_get_cipher:
* @block: the block encryption object
*
* Get the cipher to use for payload encryption
*
* Returns: the cipher object
*/
QCryptoCipher *qcrypto_block_get_cipher(QCryptoBlock *block);
/**
* qcrypto_block_get_ivgen:
* @block: the block encryption object
*
* Get the initialization vector generator to use for
* payload encryption
*
* Returns: the IV generator object
*/
QCryptoIVGen *qcrypto_block_get_ivgen(QCryptoBlock *block);
/**
* qcrypto_block_get_kdf_hash:
* @block: the block encryption object
*
* Get the hash algorithm used with the key derivation
* function
*
* Returns: the hash algorithm
*/
QCryptoHashAlgo qcrypto_block_get_kdf_hash(QCryptoBlock *block);
/**
* qcrypto_block_get_payload_offset:
* @block: the block encryption object
*
* Get the offset to the payload indicated by the
* encryption header, in bytes.
*
* Returns: the payload offset in bytes
*/
uint64_t qcrypto_block_get_payload_offset(QCryptoBlock *block);
/**
* qcrypto_block_get_sector_size:
* @block: the block encryption object
*
* Get the size of sectors used for payload encryption. A new
* IV is used at the start of each sector. The encryption
* sector size is not required to match the sector size of the
* underlying storage. For example LUKS will always use a 512
* byte sector size, even if the volume is on a disk with 4k
* sectors.
*
* Returns: the sector in bytes
*/
uint64_t qcrypto_block_get_sector_size(QCryptoBlock *block);
/**
* qcrypto_block_free:
* @block: the block encryption object
*
* Release all resources associated with the encryption
* object
*/
void qcrypto_block_free(QCryptoBlock *block);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoBlock, qcrypto_block_free)
#endif /* QCRYPTO_BLOCK_H */
+274
View File
@@ -0,0 +1,274 @@
/*
* QEMU Crypto cipher algorithms
*
* 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.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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QCRYPTO_CIPHER_H
#define QCRYPTO_CIPHER_H
#include "qapi/qapi-types-crypto.h"
typedef struct QCryptoCipher QCryptoCipher;
typedef struct QCryptoCipherDriver QCryptoCipherDriver;
/* See also "QCryptoCipherAlgo" and "QCryptoCipherMode"
* enums defined in qapi/crypto.json */
/**
* QCryptoCipher:
*
* The QCryptoCipher object provides a way to perform encryption
* and decryption of data, with a standard API, regardless of the
* algorithm used. It further isolates the calling code from the
* details of the specific underlying implementation, whether
* built-in, libgcrypt or nettle.
*
* Each QCryptoCipher object is capable of performing both
* encryption and decryption, and can operate in a number
* or modes including ECB, CBC.
*
* <example>
* <title>Encrypting data with AES-128 in CBC mode</title>
* <programlisting>
* QCryptoCipher *cipher;
* uint8_t key = ....;
* size_t keylen = 16;
* uint8_t iv = ....;
*
* if (!qcrypto_cipher_supports(QCRYPTO_CIPHER_ALGO_AES_128)) {
* error_report(errp, "Feature <blah> requires AES cipher support");
* return -1;
* }
*
* cipher = qcrypto_cipher_new(QCRYPTO_CIPHER_ALGO_AES_128,
* QCRYPTO_CIPHER_MODE_CBC,
* key, keylen,
* errp);
* if (!cipher) {
* return -1;
* }
*
* if (qcrypto_cipher_set_iv(cipher, iv, keylen, errp) < 0) {
* return -1;
* }
*
* if (qcrypto_cipher_encrypt(cipher, rawdata, encdata, datalen, errp) < 0) {
* return -1;
* }
*
* qcrypto_cipher_free(cipher);
* </programlisting>
* </example>
*
*/
struct QCryptoCipher {
QCryptoCipherAlgo alg;
QCryptoCipherMode mode;
const QCryptoCipherDriver *driver;
};
/**
* qcrypto_cipher_supports:
* @alg: the cipher algorithm
* @mode: the cipher mode
*
* Determine if @alg cipher algorithm in @mode is supported by the
* current configured build
*
* Returns: true if the algorithm is supported, false otherwise
*/
bool qcrypto_cipher_supports(QCryptoCipherAlgo alg,
QCryptoCipherMode mode);
/**
* qcrypto_cipher_get_block_len:
* @alg: the cipher algorithm
*
* Get the required data block size in bytes. When
* encrypting data, it must be a multiple of the
* block size.
*
* Returns: the block size in bytes
*/
size_t qcrypto_cipher_get_block_len(QCryptoCipherAlgo alg);
/**
* qcrypto_cipher_get_key_len:
* @alg: the cipher algorithm
*
* Get the required key size in bytes.
*
* Returns: the key size in bytes
*/
size_t qcrypto_cipher_get_key_len(QCryptoCipherAlgo alg);
/**
* qcrypto_cipher_get_iv_len:
* @alg: the cipher algorithm
* @mode: the cipher mode
*
* Get the required initialization vector size
* in bytes, if one is required.
*
* Returns: the IV size in bytes, or 0 if no IV is permitted
*/
size_t qcrypto_cipher_get_iv_len(QCryptoCipherAlgo alg,
QCryptoCipherMode mode);
/**
* qcrypto_cipher_new:
* @alg: the cipher algorithm
* @mode: the cipher usage mode
* @key: the private key bytes
* @nkey: the length of @key
* @errp: pointer to a NULL-initialized error object
*
* Creates a new cipher object for encrypting/decrypting
* data with the algorithm @alg in the usage mode @mode.
*
* The @key parameter provides the bytes representing
* the encryption/decryption key to use. The @nkey parameter
* specifies the length of @key in bytes. Each algorithm has
* one or more valid key lengths, and it is an error to provide
* a key of the incorrect length.
*
* The returned cipher object must be released with
* qcrypto_cipher_free() when no longer required
*
* Returns: a new cipher object, or NULL on error
*/
QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgo alg,
QCryptoCipherMode mode,
const uint8_t *key, size_t nkey,
Error **errp);
/**
* qcrypto_cipher_free:
* @cipher: the cipher object
*
* Release the memory associated with @cipher that
* was previously allocated by qcrypto_cipher_new()
*/
void qcrypto_cipher_free(QCryptoCipher *cipher);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoCipher, qcrypto_cipher_free)
/**
* qcrypto_cipher_encrypt:
* @cipher: the cipher object
* @in: buffer holding the plain text input data
* @out: buffer to fill with the cipher text output data
* @len: the length of @in and @out buffers
* @errp: pointer to a NULL-initialized error object
*
* Encrypts the plain text stored in @in, filling
* @out with the resulting ciphered text. Both the
* @in and @out buffers must have the same size,
* given by @len.
*
* Returns: 0 on success, or -1 on error
*/
int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
const void *in,
void *out,
size_t len,
Error **errp);
/**
* qcrypto_cipher_decrypt:
* @cipher: the cipher object
* @in: buffer holding the cipher text input data
* @out: buffer to fill with the plain text output data
* @len: the length of @in and @out buffers
* @errp: pointer to a NULL-initialized error object
*
* Decrypts the cipher text stored in @in, filling
* @out with the resulting plain text. Both the
* @in and @out buffers must have the same size,
* given by @len.
*
* Returns: 0 on success, or -1 on error
*/
int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
const void *in,
void *out,
size_t len,
Error **errp);
/**
* qcrypto_cipher_setiv:
* @cipher: the cipher object
* @iv: the initialization vector or counter (CTR mode) bytes
* @niv: the length of @iv
* @errpr: pointer to a NULL-initialized error object
*
* If the @cipher object is setup to use a mode that requires
* initialization vectors or counter, this sets the @niv
* bytes. The @iv data should have the same length as the
* cipher key used when originally constructing the cipher
* object. It is an error to set an initialization vector
* or counter if the cipher mode does not require one.
*
* Returns: 0 on success, -1 on error
*/
int qcrypto_cipher_setiv(QCryptoCipher *cipher,
const uint8_t *iv, size_t niv,
Error **errp);
/**
* qcrypto_cipher_setaad:
* @cipher: the cipher object
* @aad: the associated data to authenticate
* @len: the length of @aad
* @errp: pointer to a NULL-initialized error object
*
* For AEAD modes such as GCM, feed the associated data (AAD) that is
* authenticated but not encrypted. It must be called after
* qcrypto_cipher_setiv() and before the first encrypt/decrypt call. It is
* an error to call this on a mode that is not an AEAD mode.
*
* Returns: 0 on success, -1 on error
*/
int qcrypto_cipher_setaad(QCryptoCipher *cipher,
const uint8_t *aad, size_t len,
Error **errp);
/**
* qcrypto_cipher_gettag:
* @cipher: the cipher object
* @tag: buffer to receive the authentication tag
* @len: the length of @tag
* @errp: pointer to a NULL-initialized error object
*
* For AEAD modes such as GCM, read back the authentication tag computed
* over the associated data and the message. It must be called after the
* encrypt/decrypt operation. It is an error to call this on a mode that is
* not an AEAD mode.
*
* Returns: 0 on success, -1 on error
*/
int qcrypto_cipher_gettag(QCryptoCipher *cipher,
uint8_t *tag, size_t len,
Error **errp);
#endif /* QCRYPTO_CIPHER_H */
+83
View File
@@ -0,0 +1,83 @@
/*
* Carry-less multiply operations.
* SPDX-License-Identifier: GPL-2.0-or-later
*
* Copyright (C) 2023 Linaro, Ltd.
*/
#ifndef CRYPTO_CLMUL_H
#define CRYPTO_CLMUL_H
#include "qemu/int128.h"
#include "host/crypto/clmul.h"
/**
* clmul_8x8_low:
*
* Perform eight 8x8->8 carry-less multiplies.
*/
uint64_t clmul_8x8_low(uint64_t, uint64_t);
/**
* clmul_8x4_even:
*
* Perform four 8x8->16 carry-less multiplies.
* The odd bytes of the inputs are ignored.
*/
uint64_t clmul_8x4_even(uint64_t, uint64_t);
/**
* clmul_8x4_odd:
*
* Perform four 8x8->16 carry-less multiplies.
* The even bytes of the inputs are ignored.
*/
uint64_t clmul_8x4_odd(uint64_t, uint64_t);
/**
* clmul_8x4_packed:
*
* Perform four 8x8->16 carry-less multiplies.
*/
uint64_t clmul_8x4_packed(uint32_t, uint32_t);
/**
* clmul_16x2_even:
*
* Perform two 16x16->32 carry-less multiplies.
* The odd words of the inputs are ignored.
*/
uint64_t clmul_16x2_even(uint64_t, uint64_t);
/**
* clmul_16x2_odd:
*
* Perform two 16x16->32 carry-less multiplies.
* The even words of the inputs are ignored.
*/
uint64_t clmul_16x2_odd(uint64_t, uint64_t);
/**
* clmul_32:
*
* Perform a 32x32->64 carry-less multiply.
*/
uint64_t clmul_32(uint32_t, uint32_t);
/**
* clmul_64:
*
* Perform a 64x64->128 carry-less multiply.
*/
Int128 clmul_64_gen(uint64_t, uint64_t);
static inline Int128 clmul_64(uint64_t a, uint64_t b)
{
if (HAVE_CLMUL_ACCEL) {
return clmul_64_accel(a, b);
} else {
return clmul_64_gen(a, b);
}
}
#endif /* CRYPTO_CLMUL_H */
+50
View File
@@ -0,0 +1,50 @@
/*
* This is D3DES (V5.09) by Richard Outerbridge with the double and
* triple-length support removed for use in VNC.
*
* These changes are:
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
*
* This software 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.
*/
#ifndef QCRYPTO_DESRFB_H
#define QCRYPTO_DESRFB_H
/* d3des.h -
*
* Headers and defines for d3des.c
* Graven Imagery, 1992.
*
* Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge
* (GEnie : OUTER; CIS : [71755,204])
*/
#define EN0 0 /* MODE == encrypt */
#define DE1 1 /* MODE == decrypt */
void deskey(unsigned char *, int);
/* hexkey[8] MODE
* Sets the internal key register according to the hexadecimal
* key contained in the 8 bytes of hexkey, according to the DES,
* for encryption or decryption according to MODE.
*/
void usekey(unsigned long *);
/* cookedkey[32]
* Loads the internal key register with the data in cookedkey.
*/
void des(unsigned char *, unsigned char *);
/* from[8] to[8]
* Encrypts/Decrypts (according to the key currently loaded in the
* internal key register) one block of eight bytes at address 'from'
* into the block at address 'to'. They can be the same.
*/
/* d3des.h V5.09 rwo 9208.04 15:06 Graven Imagery
********************************************************************/
#endif
+343
View File
@@ -0,0 +1,343 @@
/*
* QEMU Crypto hash algorithms
*
* Copyright (c) 2024 Seagate Technology LLC and/or its Affiliates
* 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.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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QCRYPTO_HASH_H
#define QCRYPTO_HASH_H
#include "qapi/qapi-types-crypto.h"
#define QCRYPTO_HASH_DIGEST_LEN_MD5 16
#define QCRYPTO_HASH_DIGEST_LEN_SHA1 20
#define QCRYPTO_HASH_DIGEST_LEN_SHA224 28
#define QCRYPTO_HASH_DIGEST_LEN_SHA256 32
#define QCRYPTO_HASH_DIGEST_LEN_SHA384 48
#define QCRYPTO_HASH_DIGEST_LEN_SHA512 64
#define QCRYPTO_HASH_DIGEST_LEN_RIPEMD160 20
#define QCRYPTO_HASH_DIGEST_LEN_SM3 32
/* See also "QCryptoHashAlgo" defined in qapi/crypto.json */
typedef struct QCryptoHash QCryptoHash;
struct QCryptoHash {
QCryptoHashAlgo alg;
void *opaque;
void *driver;
};
/**
* qcrypto_hash_supports:
* @alg: the hash algorithm
*
* Determine if @alg hash algorithm is supported by the
* current configured build.
*
* Returns: true if the algorithm is supported, false otherwise
*/
gboolean qcrypto_hash_supports(QCryptoHashAlgo alg);
/**
* qcrypto_hash_digest_len:
* @alg: the hash algorithm
*
* Determine the size of the hash digest in bytes
*
* Returns: the digest length in bytes
*/
size_t qcrypto_hash_digest_len(QCryptoHashAlgo alg);
/**
* qcrypto_hash_bytesv:
* @alg: the hash algorithm
* @iov: the array of memory regions to hash
* @niov: the length of @iov
* @result: pointer to hold output hash
* @resultlen: pointer to hold length of @result
* @errp: pointer to a NULL-initialized error object
*
* Computes the hash across all the memory regions
* present in @iov.
*
* If @result_len is set to a non-zero value by the caller, then
* @result must hold a pointer that is @result_len in size, and
* @result_len match the size of the hash output. The digest will
* be written into @result.
*
* If @result_len is set to zero, then this function will allocate
* a buffer to hold the hash output digest, storing a pointer to
* the buffer in @result, and setting @result_len to its size.
* The memory referenced in @result must be released with a call
* to g_free() when no longer required by the caller.
*
* Returns: 0 on success, -1 on error
*/
int qcrypto_hash_bytesv(QCryptoHashAlgo alg,
const struct iovec *iov,
size_t niov,
uint8_t **result,
size_t *resultlen,
Error **errp);
/**
* qcrypto_hash_bytes:
* @alg: the hash algorithm
* @buf: the memory region to hash
* @len: the length of @buf
* @result: pointer to hold output hash
* @resultlen: pointer to hold length of @result
* @errp: pointer to a NULL-initialized error object
*
* Computes the hash across all the memory region
* @buf of length @len.
*
* If @result_len is set to a non-zero value by the caller, then
* @result must hold a pointer that is @result_len in size, and
* @result_len match the size of the hash output. The digest will
* be written into @result.
*
* If @result_len is set to zero, then this function will allocate
* a buffer to hold the hash output digest, storing a pointer to
* the buffer in @result, and setting @result_len to its size.
* The memory referenced in @result must be released with a call
* to g_free() when no longer required by the caller.
*
* Returns: 0 on success, -1 on error
*/
int qcrypto_hash_bytes(QCryptoHashAlgo alg,
const void *buf,
size_t len,
uint8_t **result,
size_t *resultlen,
Error **errp);
/**
* qcrypto_hash_digestv:
* @alg: the hash algorithm
* @iov: the array of memory regions to hash
* @niov: the length of @iov
* @digest: pointer to hold output hash
* @errp: pointer to a NULL-initialized error object
*
* Computes the hash across all the memory regions
* present in @iov. The @digest pointer will be
* filled with the printable hex digest of the computed
* hash, which will be terminated by '\0'. The
* memory pointer in @digest must be released
* with a call to g_free() when no longer required.
*
* Returns: 0 on success, -1 on error
*/
int qcrypto_hash_digestv(QCryptoHashAlgo alg,
const struct iovec *iov,
size_t niov,
char **digest,
Error **errp);
/**
* qcrypto_hash_updatev:
* @hash: hash object from qcrypto_hash_new
* @iov: the array of memory regions to hash
* @niov: the length of @iov
* @errp: pointer to a NULL-initialized error object
*
* Updates the given hash object with all the memory regions
* present in @iov.
*
* Returns: 0 on success, -1 on error
*/
int qcrypto_hash_updatev(QCryptoHash *hash,
const struct iovec *iov,
size_t niov,
Error **errp);
/**
* qcrypto_hash_update:
* @hash: hash object from qcrypto_hash_new
* @buf: the memory region to hash
* @len: the length of @buf
* @errp: pointer to a NULL-initialized error object
*
* Updates the given hash object with the data from
* the given buffer.
*
* Returns: 0 on success, -1 on error
*/
int qcrypto_hash_update(QCryptoHash *hash,
const void *buf,
size_t len,
Error **errp);
/**
* qcrypto_hash_finalize_digest:
* @hash: the hash object to finalize
* @digest: pointer to hold output hash
* @errp: pointer to a NULL-initialized error object
*
* Computes the hash from the given hash object. Hash object
* is expected to have its data updated from the qcrypto_hash_update function.
* The @digest pointer will be filled with the printable hex digest of the
* computed hash, which will be terminated by '\0'. The memory pointer
* in @digest must be released with a call to g_free() when
* no longer required.
*
* Returns: 0 on success, -1 on error
*/
int qcrypto_hash_finalize_digest(QCryptoHash *hash,
char **digest,
Error **errp);
/**
* qcrypto_hash_finalize_base64:
* @hash_ctx: hash object to finalize
* @base64: pointer to store the hash result in
* @errp: pointer to a NULL-initialized error object
*
* Computes the hash from the given hash object. Hash object
* is expected to have it's data updated from the qcrypto_hash_update function.
* The @base64 pointer will be filled with the base64 encoding of the computed
* hash, which will be terminated by '\0'. The memory pointer in @base64
* must be released with a call to g_free() when no longer required.
*
* Returns: 0 on success, -1 on error
*/
int qcrypto_hash_finalize_base64(QCryptoHash *hash,
char **base64,
Error **errp);
/**
* qcrypto_hash_finalize_bytes:
* @hash_ctx: hash object to finalize
* @result: pointer to store the hash result in
* @result_len: Pointer to store the length of the result in
* @errp: pointer to a NULL-initialized error object
*
* Computes the hash from the given hash object. Hash object
* is expected to have it's data updated from the qcrypto_hash_update function.
*
* If @result_len is set to a non-zero value by the caller, then
* @result must hold a pointer that is @result_len in size, and
* @result_len match the size of the hash output. The digest will
* be written into @result.
*
* If @result_len is set to zero, then this function will allocate
* a buffer to hold the hash output digest, storing a pointer to
* the buffer in @result, and setting @result_len to its size.
* The memory referenced in @result must be released with a call
* to g_free() when no longer required by the caller.
*
* Returns: 0 on success, -1 on error
*/
int qcrypto_hash_finalize_bytes(QCryptoHash *hash,
uint8_t **result,
size_t *result_len,
Error **errp);
/**
* qcrypto_hash_new:
* @alg: the hash algorithm
* @errp: pointer to a NULL-initialized error object
*
* Creates a new hashing context for the chosen algorithm for
* usage with qcrypto_hash_update.
*
* Returns: New hash object with the given algorithm, or NULL on error.
*/
QCryptoHash *qcrypto_hash_new(QCryptoHashAlgo alg, Error **errp);
/**
* qcrypto_hash_free:
* @hash: hash object to free
*
* Frees a hashing context for the chosen algorithm.
*/
void qcrypto_hash_free(QCryptoHash *hash);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoHash, qcrypto_hash_free)
/**
* qcrypto_hash_digest:
* @alg: the hash algorithm
* @buf: the memory region to hash
* @len: the length of @buf
* @digest: pointer to hold output hash
* @errp: pointer to a NULL-initialized error object
*
* Computes the hash across all the memory region
* @buf of length @len. The @digest pointer will be
* filled with the printable hex digest of the computed
* hash, which will be terminated by '\0'. The
* memory pointer in @digest must be released
* with a call to g_free() when no longer required.
*
* Returns: 0 on success, -1 on error
*/
int qcrypto_hash_digest(QCryptoHashAlgo alg,
const void *buf,
size_t len,
char **digest,
Error **errp);
/**
* qcrypto_hash_base64v:
* @alg: the hash algorithm
* @iov: the array of memory regions to hash
* @niov: the length of @iov
* @base64: pointer to hold output hash
* @errp: pointer to a NULL-initialized error object
*
* Computes the hash across all the memory regions
* present in @iov. The @base64 pointer will be
* filled with the base64 encoding of the computed
* hash, which will be terminated by '\0'. The
* memory pointer in @base64 must be released
* with a call to g_free() when no longer required.
*
* Returns: 0 on success, -1 on error
*/
int qcrypto_hash_base64v(QCryptoHashAlgo alg,
const struct iovec *iov,
size_t niov,
char **base64,
Error **errp);
/**
* qcrypto_hash_base64:
* @alg: the hash algorithm
* @buf: the memory region to hash
* @len: the length of @buf
* @base64: pointer to hold output hash
* @errp: pointer to a NULL-initialized error object
*
* Computes the hash across all the memory region
* @buf of length @len. The @base64 pointer will be
* filled with the base64 encoding of the computed
* hash, which will be terminated by '\0'. The
* memory pointer in @base64 must be released
* with a call to g_free() when no longer required.
*
* Returns: 0 on success, -1 on error
*/
int qcrypto_hash_base64(QCryptoHashAlgo alg,
const void *buf,
size_t len,
char **base64,
Error **errp);
#endif /* QCRYPTO_HASH_H */
+195
View File
@@ -0,0 +1,195 @@
/*
* QEMU Crypto hmac algorithms
*
* Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
*
* This work is licensed under the terms of the GNU GPL, version 2 or
* (at your option) any later version. See the COPYING file in the
* top-level directory.
*
*/
#ifndef QCRYPTO_HMAC_H
#define QCRYPTO_HMAC_H
#include "qapi/qapi-types-crypto.h"
typedef struct QCryptoHmac QCryptoHmac;
struct QCryptoHmac {
QCryptoHashAlgo alg;
void *opaque;
void *driver;
};
/**
* qcrypto_hmac_supports:
* @alg: the hmac algorithm
*
* Determine if @alg hmac algorithm is supported by
* the current configured build
*
* Returns:
* true if the algorithm is supported, false otherwise
*/
bool qcrypto_hmac_supports(QCryptoHashAlgo alg);
/**
* qcrypto_hmac_new:
* @alg: the hmac algorithm
* @key: the key bytes
* @nkey: the length of @key
* @errp: pointer to a NULL-initialized error object
*
* Creates a new hmac object with the algorithm @alg
*
* The @key parameter provides the bytes representing
* the secret key to use. The @nkey parameter specifies
* the length of @key in bytes
*
* Note: must use qcrypto_hmac_free() to release the
* returned hmac object when no longer required
*
* Returns:
* a new hmac object, or NULL on error
*/
QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgo alg,
const uint8_t *key, size_t nkey,
Error **errp);
/**
* qcrypto_hmac_free:
* @hmac: the hmac object
*
* Release the memory associated with @hmac that was
* previously allocated by qcrypto_hmac_new()
*/
void qcrypto_hmac_free(QCryptoHmac *hmac);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoHmac, qcrypto_hmac_free)
/**
* qcrypto_hmac_bytesv:
* @hmac: the hmac object
* @iov: the array of memory regions to hmac
* @niov: the length of @iov
* @result: pointer to hold output hmac
* @resultlen: pointer to hold length of @result
* @errp: pointer to a NULL-initialized error object
*
* Computes the hmac across all the memory regions
* present in @iov.
*
* If @result_len is set to a non-zero value by the caller, then
* @result must hold a pointer that is @result_len in size, and
* @result_len match the size of the hash output. The digest will
* be written into @result.
*
* If @result_len is set to zero, then this function will allocate
* a buffer to hold the hash output digest, storing a pointer to
* the buffer in @result, and setting @result_len to its size.
* The memory referenced in @result must be released with a call
* to g_free() when no longer required by the caller.
*
* If @result_len is set to a NULL pointer, no result will be returned, and
* the hmac object can be used for further invocations of qcrypto_hmac_bytes()
* or qcrypto_hmac_bytesv() until a non-NULL pointer is provided. This allows
* to build the hmac across memory regions that are not available at the same
* time.
*
* Returns:
* 0 on success, -1 on error
*/
int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
const struct iovec *iov,
size_t niov,
uint8_t **result,
size_t *resultlen,
Error **errp);
/**
* qcrypto_hmac_bytes:
* @hmac: the hmac object
* @buf: the memory region to hmac
* @len: the length of @buf
* @result: pointer to hold output hmac
* @resultlen: pointer to hold length of @result
* @errp: pointer to a NULL-initialized error object
*
* Computes the hmac across all the memory region
* @buf of length @len.
*
* If @result_len is set to a non-zero value by the caller, then
* @result must hold a pointer that is @result_len in size, and
* @result_len match the size of the hash output. The digest will
* be written into @result.
*
* If @result_len is set to zero, then this function will allocate
* a buffer to hold the hash output digest, storing a pointer to
* the buffer in @result, and setting @result_len to its size.
* The memory referenced in @result must be released with a call
* to g_free() when no longer required by the caller.
*
* If @result_len is set to a NULL pointer, no result will be returned, and
* the hmac object can be used for further invocations of qcrypto_hmac_bytes()
* or qcrypto_hmac_bytesv() until a non-NULL pointer is provided. This allows
* to build the hmac across memory regions that are not available at the same
* time.
*
* Returns:
* 0 on success, -1 on error
*/
int qcrypto_hmac_bytes(QCryptoHmac *hmac,
const void *buf,
size_t len,
uint8_t **result,
size_t *resultlen,
Error **errp);
/**
* qcrypto_hmac_digestv:
* @hmac: the hmac object
* @iov: the array of memory regions to hmac
* @niov: the length of @iov
* @digest: pointer to hold output hmac
* @errp: pointer to a NULL-initialized error object
*
* Computes the hmac across all the memory regions
* present in @iov. The @digest pointer will be
* filled with the printable hex digest of the computed
* hmac, which will be terminated by '\0'. The
* memory pointer in @digest must be released
* with a call to g_free() when no longer required.
*
* Returns:
* 0 on success, -1 on error
*/
int qcrypto_hmac_digestv(QCryptoHmac *hmac,
const struct iovec *iov,
size_t niov,
char **digest,
Error **errp);
/**
* qcrypto_hmac_digest:
* @hmac: the hmac object
* @buf: the memory region to hmac
* @len: the length of @buf
* @digest: pointer to hold output hmac
* @errp: pointer to a NULL-initialized error object
*
* Computes the hmac across all the memory region
* @buf of length @len. The @digest pointer will be
* filled with the printable hex digest of the computed
* hmac, which will be terminated by '\0'. The
* memory pointer in @digest must be released
* with a call to g_free() when no longer required.
*
* Returns: 0 on success, -1 on error
*/
int qcrypto_hmac_digest(QCryptoHmac *hmac,
const void *buf,
size_t len,
char **digest,
Error **errp);
#endif
+28
View File
@@ -0,0 +1,28 @@
/*
* QEMU Crypto initialization
*
* 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.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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QCRYPTO_INIT_H
#define QCRYPTO_INIT_H
#include "qapi/error.h"
int qcrypto_init(Error **errp);
#endif /* QCRYPTO_INIT_H */
+208
View File
@@ -0,0 +1,208 @@
/*
* QEMU Crypto block IV generator
*
* Copyright (c) 2015-2016 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.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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QCRYPTO_IVGEN_H
#define QCRYPTO_IVGEN_H
#include "crypto/cipher.h"
#include "crypto/hash.h"
/**
* This module provides a framework for generating initialization
* vectors for block encryption schemes using chained cipher modes
* CBC. The principle is that each disk sector is assigned a unique
* initialization vector for use for encryption of data in that
* sector.
*
* <example>
* <title>Encrypting block data with initialization vectors</title>
* <programlisting>
* uint8_t *data = ....data to encrypt...
* size_t ndata = XXX;
* uint8_t *key = ....some encryption key...
* size_t nkey = XXX;
* uint8_t *iv;
* size_t niv;
* size_t sector = 0;
*
* g_assert((ndata % 512) == 0);
*
* QCryptoIVGen *ivgen = qcrypto_ivgen_new(QCRYPTO_IV_GEN_ALGO_ESSIV,
* QCRYPTO_CIPHER_ALGO_AES_128,
* QCRYPTO_HASH_ALGO_SHA256,
* key, nkey, errp);
* if (!ivgen) {
* return -1;
* }
*
* QCryptoCipher *cipher = qcrypto_cipher_new(QCRYPTO_CIPHER_ALGO_AES_128,
* QCRYPTO_CIPHER_MODE_CBC,
* key, nkey, errp);
* if (!cipher) {
* goto error;
* }
*
* niv = qcrypto_cipher_get_iv_len(QCRYPTO_CIPHER_ALGO_AES_128,
* QCRYPTO_CIPHER_MODE_CBC);
* iv = g_new0(uint8_t, niv);
*
*
* while (ndata) {
* if (qcrypto_ivgen_calculate(ivgen, sector, iv, niv, errp) < 0) {
* goto error;
* }
* if (qcrypto_cipher_setiv(cipher, iv, niv, errp) < 0) {
* goto error;
* }
* if (qcrypto_cipher_encrypt(cipher,
* data + (sector * 512),
* data + (sector * 512),
* 512, errp) < 0) {
* goto error;
* }
* sector++;
* ndata -= 512;
* }
*
* g_free(iv);
* qcrypto_ivgen_free(ivgen);
* qcrypto_cipher_free(cipher);
* return 0;
*
*error:
* g_free(iv);
* qcrypto_ivgen_free(ivgen);
* qcrypto_cipher_free(cipher);
* return -1;
* </programlisting>
* </example>
*/
typedef struct QCryptoIVGen QCryptoIVGen;
/* See also QCryptoIVGenAlgo enum in qapi/crypto.json */
/**
* qcrypto_ivgen_new:
* @alg: the initialization vector generation algorithm
* @cipheralg: the cipher algorithm or 0
* @hash: the hash algorithm or 0
* @key: the encryption key or NULL
* @nkey: the size of @key in bytes
*
* Create a new initialization vector generator that uses
* the algorithm @alg. Whether the remaining parameters
* are required or not depends on the choice of @alg
* requested.
*
* - QCRYPTO_IV_GEN_ALGO_PLAIN
*
* The IVs are generated by the 32-bit truncated sector
* number. This should never be used for block devices
* that are larger than 2^32 sectors in size.
* All the other parameters are unused.
*
* - QCRYPTO_IV_GEN_ALGO_PLAIN64
*
* The IVs are generated by the 64-bit sector number.
* All the other parameters are unused.
*
* - QCRYPTO_IV_GEN_ALGO_ESSIV:
*
* The IVs are generated by encrypting the 64-bit sector
* number with a hash of an encryption key. The @cipheralg,
* @hash, @key and @nkey parameters are all required.
*
* Returns: a new IV generator, or NULL on error
*/
QCryptoIVGen *qcrypto_ivgen_new(QCryptoIVGenAlgo alg,
QCryptoCipherAlgo cipheralg,
QCryptoHashAlgo hash,
const uint8_t *key, size_t nkey,
Error **errp);
/**
* qcrypto_ivgen_calculate:
* @ivgen: the IV generator object
* @sector: the 64-bit sector number
* @iv: a pre-allocated buffer to hold the generated IV
* @niv: the number of bytes in @iv
* @errp: pointer to a NULL-initialized error object
*
* Calculate a new initialization vector for the data
* to be stored in sector @sector. The IV will be
* written into the buffer @iv of size @niv.
*
* Returns: 0 on success, -1 on error
*/
int qcrypto_ivgen_calculate(QCryptoIVGen *ivgen,
uint64_t sector,
uint8_t *iv, size_t niv,
Error **errp);
/**
* qcrypto_ivgen_get_algorithm:
* @ivgen: the IV generator object
*
* Get the algorithm used by this IV generator
*
* Returns: the IV generator algorithm
*/
QCryptoIVGenAlgo qcrypto_ivgen_get_algorithm(QCryptoIVGen *ivgen);
/**
* qcrypto_ivgen_get_cipher:
* @ivgen: the IV generator object
*
* Get the cipher algorithm used by this IV generator (if
* applicable)
*
* Returns: the cipher algorithm
*/
QCryptoCipherAlgo qcrypto_ivgen_get_cipher(QCryptoIVGen *ivgen);
/**
* qcrypto_ivgen_get_hash:
* @ivgen: the IV generator object
*
* Get the hash algorithm used by this IV generator (if
* applicable)
*
* Returns: the hash algorithm
*/
QCryptoHashAlgo qcrypto_ivgen_get_hash(QCryptoIVGen *ivgen);
/**
* qcrypto_ivgen_free:
* @ivgen: the IV generator object
*
* Release all resources associated with @ivgen, or a no-op
* if @ivgen is NULL
*/
void qcrypto_ivgen_free(QCryptoIVGen *ivgen);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoIVGen, qcrypto_ivgen_free)
#endif /* QCRYPTO_IVGEN_H */
+156
View File
@@ -0,0 +1,156 @@
/*
* QEMU Crypto PBKDF support (Password-Based Key Derivation Function)
*
* Copyright (c) 2015-2016 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.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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QCRYPTO_PBKDF_H
#define QCRYPTO_PBKDF_H
#include "crypto/hash.h"
/**
* This module provides an interface to the PBKDF2 algorithm
*
* https://en.wikipedia.org/wiki/PBKDF2
*
* <example>
* <title>Generating an AES encryption key from a user password</title>
* <programlisting>
* #include "crypto/cipher.h"
* #include "crypto/random.h"
* #include "crypto/pbkdf.h"
*
* ....
*
* char *password = "a-typical-awful-user-password";
* size_t nkey = qcrypto_cipher_get_key_len(QCRYPTO_CIPHER_ALGO_AES_128);
* uint8_t *salt = g_new0(uint8_t, nkey);
* uint8_t *key = g_new0(uint8_t, nkey);
* int iterations;
* QCryptoCipher *cipher;
*
* if (qcrypto_random_bytes(salt, nkey, errp) < 0) {
* g_free(key);
* g_free(salt);
* return -1;
* }
*
* iterations = qcrypto_pbkdf2_count_iters(QCRYPTO_HASH_ALGO_SHA256,
* (const uint8_t *)password,
* strlen(password),
* salt, nkey, errp);
* if (iterations < 0) {
* g_free(key);
* g_free(salt);
* return -1;
* }
*
* if (qcrypto_pbkdf2(QCRYPTO_HASH_ALGO_SHA256,
* (const uint8_t *)password, strlen(password),
* salt, nkey, iterations, key, nkey, errp) < 0) {
* g_free(key);
* g_free(salt);
* return -1;
* }
*
* g_free(salt);
*
* cipher = qcrypto_cipher_new(QCRYPTO_CIPHER_ALGO_AES_128,
* QCRYPTO_CIPHER_MODE_ECB,
* key, nkey, errp);
* g_free(key);
*
* ....encrypt some data...
*
* qcrypto_cipher_free(cipher);
* </programlisting>
* </example>
*
*/
/**
* qcrypto_pbkdf2_supports:
* @hash: the hash algorithm
*
* Determine if the current build supports the PBKDF2 algorithm
* in combination with the hash @hash.
*
* Returns true if supported, false otherwise
*/
bool qcrypto_pbkdf2_supports(QCryptoHashAlgo hash);
/**
* qcrypto_pbkdf2:
* @hash: the hash algorithm to use
* @key: the user password / key
* @nkey: the length of @key in bytes
* @salt: a random salt
* @nsalt: length of @salt in bytes
* @iterations: the number of iterations to compute
* @out: pointer to pre-allocated buffer to hold output
* @nout: length of @out in bytes
* @errp: pointer to a NULL-initialized error object
*
* Apply the PBKDF2 algorithm to derive an encryption
* key from a user password provided in @key. The
* @salt parameter is used to perturb the algorithm.
* The @iterations count determines how many times
* the hashing process is run, which influences how
* hard it is to crack the key. The number of @iterations
* should be large enough such that the algorithm takes
* 1 second or longer to derive a key. The derived key
* will be stored in the preallocated buffer @out.
*
* Returns: 0 on success, -1 on error
*/
int qcrypto_pbkdf2(QCryptoHashAlgo hash,
const uint8_t *key, size_t nkey,
const uint8_t *salt, size_t nsalt,
uint64_t iterations,
uint8_t *out, size_t nout,
Error **errp);
/**
* qcrypto_pbkdf2_count_iters:
* @hash: the hash algorithm to use
* @key: the user password / key
* @nkey: the length of @key in bytes
* @salt: a random salt
* @nsalt: length of @salt in bytes
* @nout: size of desired derived key
* @errp: pointer to a NULL-initialized error object
*
* Time the PBKDF2 algorithm to determine how many
* iterations are required to derive an encryption
* key from a user password provided in @key in 1
* second of compute time. The result of this can
* be used as a the @iterations parameter of a later
* call to qcrypto_pbkdf2(). The value of @nout should
* match that value that will later be provided with
* a call to qcrypto_pbkdf2().
*
* Returns: number of iterations in 1 second, -1 on error
*/
uint64_t qcrypto_pbkdf2_count_iters(QCryptoHashAlgo hash,
const uint8_t *key, size_t nkey,
const uint8_t *salt, size_t nsalt,
size_t nout,
Error **errp);
#endif /* QCRYPTO_PBKDF_H */
+50
View File
@@ -0,0 +1,50 @@
/*
* QEMU Crypto random number provider
*
* Copyright (c) 2015-2016 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.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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QCRYPTO_RANDOM_H
#define QCRYPTO_RANDOM_H
/**
* qcrypto_random_bytes:
* @buf: the buffer to fill
* @buflen: length of @buf in bytes
* @errp: pointer to a NULL-initialized error object
*
* Fill @buf with @buflen bytes of cryptographically strong
* random data
*
* Returns 0 on success, -1 on error
*/
int qcrypto_random_bytes(void *buf,
size_t buflen,
Error **errp);
/**
* qcrypto_random_init:
* @errp: pointer to a NULL-initialized error object
*
* Initializes the handles used by qcrypto_random_bytes
*
* Returns 0 on success, -1 on error
*/
int qcrypto_random_init(Error **errp);
#endif /* QCRYPTO_RANDOM_H */
+133
View File
@@ -0,0 +1,133 @@
/*
* 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.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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QCRYPTO_SECRET_H
#define QCRYPTO_SECRET_H
#include "qapi/qapi-types-crypto.h"
#include "qom/object.h"
#include "crypto/secret_common.h"
#define TYPE_QCRYPTO_SECRET "secret"
typedef struct QCryptoSecret QCryptoSecret;
DECLARE_INSTANCE_CHECKER(QCryptoSecret, QCRYPTO_SECRET,
TYPE_QCRYPTO_SECRET)
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 {
QCryptoSecretCommon parent_obj;
char *data;
char *file;
};
struct QCryptoSecretClass {
QCryptoSecretCommonClass parent_class;
};
#endif /* QCRYPTO_SECRET_H */
+58
View File
@@ -0,0 +1,58 @@
/*
* 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.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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QCRYPTO_SECRET_COMMON_H
#define QCRYPTO_SECRET_COMMON_H
#include "qapi/qapi-types-crypto.h"
#include "qom/object.h"
#define TYPE_QCRYPTO_SECRET_COMMON "secret_common"
OBJECT_DECLARE_TYPE(QCryptoSecretCommon, QCryptoSecretCommonClass,
QCRYPTO_SECRET_COMMON)
struct QCryptoSecretCommon {
Object parent_obj;
uint8_t *rawdata;
size_t rawlen;
QCryptoSecretFormat format;
char *keyid;
char *iv;
};
struct QCryptoSecretCommonClass {
ObjectClass parent_class;
void (*load_data)(QCryptoSecretCommon *secret,
uint8_t **output,
size_t *outputlen,
Error **errp);
};
int qcrypto_secret_lookup(const char *secretid,
uint8_t **data,
size_t *datalen,
Error **errp);
char *qcrypto_secret_lookup_as_utf8(const char *secretid, Error **errp);
char *qcrypto_secret_lookup_as_base64(const char *secretid, Error **errp);
#endif /* QCRYPTO_SECRET_COMMON_H */
+40
View File
@@ -0,0 +1,40 @@
/*
* QEMU crypto secret support
*
* Copyright 2020 Yandex N.V.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QCRYPTO_SECRET_KEYRING_H
#define QCRYPTO_SECRET_KEYRING_H
#include "qapi/qapi-types-crypto.h"
#include "qom/object.h"
#include "crypto/secret_common.h"
#define TYPE_QCRYPTO_SECRET_KEYRING "secret_keyring"
OBJECT_DECLARE_SIMPLE_TYPE(QCryptoSecretKeyring,
QCRYPTO_SECRET_KEYRING)
struct QCryptoSecretKeyring {
QCryptoSecretCommon parent;
int32_t serial;
};
#endif /* QCRYPTO_SECRET_KEYRING_H */
+15
View File
@@ -0,0 +1,15 @@
#ifndef QEMU_SM4_H
#define QEMU_SM4_H
extern const uint8_t sm4_sbox[256];
extern const uint32_t sm4_ck[32];
static inline uint32_t sm4_subword(uint32_t word)
{
return sm4_sbox[word & 0xff] |
sm4_sbox[(word >> 8) & 0xff] << 8 |
sm4_sbox[(word >> 16) & 0xff] << 16 |
sm4_sbox[(word >> 24) & 0xff] << 24;
}
#endif
+34
View File
@@ -0,0 +1,34 @@
/*
* QEMU TLS Cipher Suites Registry (RFC8447)
*
* Copyright (c) 2018-2020 Red Hat, Inc.
*
* Author: Philippe Mathieu-Daudé
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef QCRYPTO_TLS_CIPHER_SUITES_H
#define QCRYPTO_TLS_CIPHER_SUITES_H
#include "qom/object.h"
#include "crypto/tlscreds.h"
#define TYPE_QCRYPTO_TLS_CIPHER_SUITES "tls-cipher-suites"
typedef struct QCryptoTLSCipherSuites QCryptoTLSCipherSuites;
DECLARE_INSTANCE_CHECKER(QCryptoTLSCipherSuites, QCRYPTO_TLS_CIPHER_SUITES,
TYPE_QCRYPTO_TLS_CIPHER_SUITES)
/**
* qcrypto_tls_cipher_suites_get_data:
* @obj: pointer to a TLS cipher suites object
* @errp: pointer to a NULL-initialized error object
*
* Returns: reference to a byte array containing the data.
* The caller should release the reference when no longer
* required.
*/
GByteArray *qcrypto_tls_cipher_suites_get_data(QCryptoTLSCipherSuites *obj,
Error **errp);
#endif /* QCRYPTO_TLS_CIPHER_SUITES_H */
+93
View File
@@ -0,0 +1,93 @@
/*
* QEMU crypto TLS credential 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.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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QCRYPTO_TLSCREDS_H
#define QCRYPTO_TLSCREDS_H
#include "qapi/qapi-types-crypto.h"
#include "qom/object.h"
#define TYPE_QCRYPTO_TLS_CREDS "tls-creds"
typedef struct QCryptoTLSCreds QCryptoTLSCreds;
typedef struct QCryptoTLSCredsClass QCryptoTLSCredsClass;
DECLARE_OBJ_CHECKERS(QCryptoTLSCreds, QCryptoTLSCredsClass, QCRYPTO_TLS_CREDS,
TYPE_QCRYPTO_TLS_CREDS)
#define QCRYPTO_TLS_CREDS_DH_PARAMS "dh-params.pem"
typedef bool (*CryptoTLSCredsReload)(QCryptoTLSCreds *, Error **);
/**
* QCryptoTLSCreds:
*
* The QCryptoTLSCreds object is an abstract base for different
* types of TLS handshake credentials. Most commonly the
* QCryptoTLSCredsX509 subclass will be used to provide x509
* certificate credentials.
*/
struct QCryptoTLSCredsClass {
ObjectClass parent_class;
CryptoTLSCredsReload reload;
const char *prioritySuffix;
};
/**
* qcrypto_tls_creds_check_endpoint:
* @creds: pointer to a TLS credentials object
* @endpoint: type of network endpoint that will be using the credentials
* @errp: pointer to a NULL-initialized error object
*
* Check whether the credentials is setup according to
* the type of @endpoint argument.
*
* Returns true if the credentials is setup for the endpoint, false otherwise
*/
bool qcrypto_tls_creds_check_endpoint(QCryptoTLSCreds *creds,
QCryptoTLSCredsEndpoint endpoint,
Error **errp);
/**
* qcrypto_tls_creds_get_priority:
* @creds: pointer to a TLS credentials object
*
* Get the TLS credentials priority string. The caller
* must free the returned string when no longer required.
*
* Returns: a non-NULL priority string
*/
char *qcrypto_tls_creds_get_priority(QCryptoTLSCreds *creds);
/**
* qcrypto_tls_creds_reload:
* @creds: pointer to a TLS credentials object
* @errp: pointer to a NULL-initialized error object
*
* Request a reload of the TLS credentials, if supported
*
* Returns: true on success, false on error or if not supported
*/
bool qcrypto_tls_creds_reload(QCryptoTLSCreds *creds,
Error **errp);
#endif /* QCRYPTO_TLSCREDS_H */
+100
View File
@@ -0,0 +1,100 @@
/*
* QEMU crypto TLS anonymous credential 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.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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QCRYPTO_TLSCREDSANON_H
#define QCRYPTO_TLSCREDSANON_H
#include "crypto/tlscreds.h"
#include "qom/object.h"
#define TYPE_QCRYPTO_TLS_CREDS_ANON "tls-creds-anon"
typedef struct QCryptoTLSCredsAnon QCryptoTLSCredsAnon;
DECLARE_INSTANCE_CHECKER(QCryptoTLSCredsAnon, QCRYPTO_TLS_CREDS_ANON,
TYPE_QCRYPTO_TLS_CREDS_ANON)
typedef struct QCryptoTLSCredsAnonClass QCryptoTLSCredsAnonClass;
/**
* QCryptoTLSCredsAnon:
*
* The QCryptoTLSCredsAnon object provides a representation
* of anonymous credentials used perform a TLS handshake.
* This is primarily provided for backwards compatibility and
* its use is discouraged as it has poor security characteristics
* due to lacking MITM attack protection amongst other problems.
*
* This is a user creatable object, which can be instantiated
* via object_new_propv():
*
* <example>
* <title>Creating anonymous TLS credential objects in code</title>
* <programlisting>
* Object *obj;
* Error *err = NULL;
* obj = object_new_propv(TYPE_QCRYPTO_TLS_CREDS_ANON,
* "tlscreds0",
* &err,
* "endpoint", "server",
* "dir", "/path/x509/cert/dir",
* "verify-peer", "yes",
* NULL);
* </programlisting>
* </example>
*
* Or via QMP:
*
* <example>
* <title>Creating anonymous TLS credential objects via QMP</title>
* <programlisting>
* {
* "execute": "object-add", "arguments": {
* "id": "tlscreds0",
* "qom-type": "tls-creds-anon",
* "props": {
* "endpoint": "server",
* "dir": "/path/to/x509/cert/dir",
* "verify-peer": false
* }
* }
* }
* </programlisting>
* </example>
*
*
* Or via the CLI:
*
* <example>
* <title>Creating anonymous TLS credential objects via CLI</title>
* <programlisting>
* qemu-system-x86_64 -object tls-creds-anon,id=tlscreds0,\
* endpoint=server,verify-peer=off,\
* dir=/path/to/x509/certdir/
* </programlisting>
* </example>
*
*/
struct QCryptoTLSCredsAnonClass {
QCryptoTLSCredsClass parent_class;
};
#endif /* QCRYPTO_TLSCREDSANON_H */
+95
View File
@@ -0,0 +1,95 @@
/*
* QEMU crypto TLS Pre-Shared Key (PSK) support
*
* Copyright (c) 2018 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.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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QCRYPTO_TLSCREDSPSK_H
#define QCRYPTO_TLSCREDSPSK_H
#include "crypto/tlscreds.h"
#include "qom/object.h"
#define TYPE_QCRYPTO_TLS_CREDS_PSK "tls-creds-psk"
typedef struct QCryptoTLSCredsPSK QCryptoTLSCredsPSK;
DECLARE_INSTANCE_CHECKER(QCryptoTLSCredsPSK, QCRYPTO_TLS_CREDS_PSK,
TYPE_QCRYPTO_TLS_CREDS_PSK)
typedef struct QCryptoTLSCredsPSKClass QCryptoTLSCredsPSKClass;
#define QCRYPTO_TLS_CREDS_PSKFILE "keys.psk"
/**
* QCryptoTLSCredsPSK:
*
* The QCryptoTLSCredsPSK object provides a representation
* of the Pre-Shared Key credential used to perform a TLS handshake.
*
* This is a user creatable object, which can be instantiated
* via object_new_propv():
*
* <example>
* <title>Creating TLS-PSK credential objects in code</title>
* <programlisting>
* Object *obj;
* Error *err = NULL;
* obj = object_new_propv(TYPE_QCRYPTO_TLS_CREDS_PSK,
* "tlscreds0",
* &err,
* "dir", "/path/to/dir",
* "endpoint", "client",
* NULL);
* </programlisting>
* </example>
*
* Or via QMP:
*
* <example>
* <title>Creating TLS-PSK credential objects via QMP</title>
* <programlisting>
* {
* "execute": "object-add", "arguments": {
* "id": "tlscreds0",
* "qom-type": "tls-creds-psk",
* "props": {
* "dir": "/path/to/dir",
* "endpoint": "client"
* }
* }
* }
* </programlisting>
* </example>
*
* Or via the CLI:
*
* <example>
* <title>Creating TLS-PSK credential objects via CLI</title>
* <programlisting>
* qemu-system-x86_64 --object tls-creds-psk,id=tlscreds0,\
* endpoint=client,dir=/path/to/dir[,username=qemu]
* </programlisting>
* </example>
*
* The PSK file can be created and managed using psktool.
*/
struct QCryptoTLSCredsPSKClass {
QCryptoTLSCredsClass parent_class;
};
#endif /* QCRYPTO_TLSCREDSPSK_H */
+110
View File
@@ -0,0 +1,110 @@
/*
* QEMU crypto TLS x509 credential 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.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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QCRYPTO_TLSCREDSX509_H
#define QCRYPTO_TLSCREDSX509_H
#include "crypto/tlscreds.h"
#include "qom/object.h"
#define TYPE_QCRYPTO_TLS_CREDS_X509 "tls-creds-x509"
typedef struct QCryptoTLSCredsX509 QCryptoTLSCredsX509;
DECLARE_INSTANCE_CHECKER(QCryptoTLSCredsX509, QCRYPTO_TLS_CREDS_X509,
TYPE_QCRYPTO_TLS_CREDS_X509)
typedef struct QCryptoTLSCredsX509Class QCryptoTLSCredsX509Class;
#define QCRYPTO_TLS_CREDS_X509_CA_CERT "ca-cert.pem"
#define QCRYPTO_TLS_CREDS_X509_CA_CRL "ca-crl.pem"
#define QCRYPTO_TLS_CREDS_X509_SERVER_KEY "server-key.pem"
#define QCRYPTO_TLS_CREDS_X509_SERVER_CERT "server-cert.pem"
#define QCRYPTO_TLS_CREDS_X509_CLIENT_KEY "client-key.pem"
#define QCRYPTO_TLS_CREDS_X509_CLIENT_CERT "client-cert.pem"
#define QCRYPTO_TLS_CREDS_X509_SERVER_KEY_N "server-key-%zu.pem"
#define QCRYPTO_TLS_CREDS_X509_SERVER_CERT_N "server-cert-%zu.pem"
#define QCRYPTO_TLS_CREDS_X509_CLIENT_KEY_N "client-key-%zu.pem"
#define QCRYPTO_TLS_CREDS_X509_CLIENT_CERT_N "client-cert-%zu.pem"
/* Max number of additional cert/key pairs (ie _N constants) */
#define QCRYPTO_TLS_CREDS_X509_IDENTITY_MAX 4
/**
* QCryptoTLSCredsX509:
*
* The QCryptoTLSCredsX509 object provides a representation
* of x509 credentials used to perform a TLS handshake.
*
* This is a user creatable object, which can be instantiated
* via object_new_propv():
*
* <example>
* <title>Creating x509 TLS credential objects in code</title>
* <programlisting>
* Object *obj;
* Error *err = NULL;
* obj = object_new_propv(TYPE_QCRYPTO_TLS_CREDS_X509,
* "tlscreds0",
* &err,
* "endpoint", "server",
* "dir", "/path/x509/cert/dir",
* "verify-peer", "yes",
* NULL);
* </programlisting>
* </example>
*
* Or via QMP:
*
* <example>
* <title>Creating x509 TLS credential objects via QMP</title>
* <programlisting>
* {
* "execute": "object-add", "arguments": {
* "id": "tlscreds0",
* "qom-type": "tls-creds-x509",
* "props": {
* "endpoint": "server",
* "dir": "/path/to/x509/cert/dir",
* "verify-peer": false
* }
* }
* }
* </programlisting>
* </example>
*
*
* Or via the CLI:
*
* <example>
* <title>Creating x509 TLS credential objects via CLI</title>
* <programlisting>
* qemu-system-x86_64 -object tls-creds-x509,id=tlscreds0,\
* endpoint=server,verify-peer=off,\
* dir=/path/to/x509/certdir/
* </programlisting>
* </example>
*
*/
struct QCryptoTLSCredsX509Class {
QCryptoTLSCredsClass parent_class;
};
#endif /* QCRYPTO_TLSCREDSX509_H */
+372
View File
@@ -0,0 +1,372 @@
/*
* QEMU crypto TLS session 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.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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QCRYPTO_TLSSESSION_H
#define QCRYPTO_TLSSESSION_H
#include "crypto/tlscreds.h"
/**
* QCryptoTLSSession:
*
* The QCryptoTLSSession object encapsulates the
* logic to integrate with a TLS providing library such
* as GNUTLS, to setup and run TLS sessions.
*
* The API is designed such that it has no assumption about
* the type of transport it is running over. It may be a
* traditional TCP socket, or something else entirely. The
* only requirement is a full-duplex stream of some kind.
*
* <example>
* <title>Using TLS session objects</title>
* <programlisting>
* static ssize_t mysock_send(const char *buf, size_t len,
* void *opaque)
* {
* int fd = GPOINTER_TO_INT(opaque);
*
* return write(*fd, buf, len);
* }
*
* static ssize_t mysock_recv(const char *buf, size_t len,
* void *opaque)
* {
* int fd = GPOINTER_TO_INT(opaque);
*
* return read(*fd, buf, len);
* }
*
* static int mysock_run_tls(int sockfd,
* QCryptoTLSCreds *creds,
* Error **errp)
* {
* QCryptoTLSSession *sess;
*
* sess = qcrypto_tls_session_new(creds,
* "vnc.example.com",
* NULL,
* QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT,
* errp);
* if (sess == NULL) {
* return -1;
* }
*
* qcrypto_tls_session_set_callbacks(sess,
* mysock_send,
* mysock_recv
* GINT_TO_POINTER(fd));
*
* while (1) {
* int ret = qcrypto_tls_session_handshake(sess, errp);
*
* if (ret < 0) {
* qcrypto_tls_session_free(sess);
* return -1;
* }
*
* switch(ret) {
* case QCRYPTO_TLS_HANDSHAKE_COMPLETE:
* if (qcrypto_tls_session_check_credentials(sess, errp) < )) {
* qcrypto_tls_session_free(sess);
* return -1;
* }
* goto done;
* case QCRYPTO_TLS_HANDSHAKE_RECVING:
* ...wait for GIO_IN event on fd...
* break;
* case QCRYPTO_TLS_HANDSHAKE_SENDING:
* ...wait for GIO_OUT event on fd...
* break;
* }
* }
* done:
*
* ....send/recv payload data on sess...
*
* qcrypto_tls_session_free(sess):
* }
* </programlisting>
* </example>
*/
typedef struct QCryptoTLSSession QCryptoTLSSession;
#define QCRYPTO_TLS_SESSION_ERR_BLOCK -2
#define QCRYPTO_TLS_SESSION_PREMATURE_TERMINATION -3
/**
* qcrypto_tls_session_new:
* @creds: pointer to a TLS credentials object
* @hostname: optional hostname to validate
* @aclname: optional ACL to validate peer credentials against
* @endpoint: role of the TLS session, client or server
* @errp: pointer to a NULL-initialized error object
*
* Create a new TLS session object that will be used to
* negotiate a TLS session over an arbitrary data channel.
* The session object can operate as either the server or
* client, according to the value of the @endpoint argument.
*
* For clients, the @hostname parameter should hold the full
* unmodified hostname as requested by the user. This will
* be used to verify the against the hostname reported in
* the server's credentials (aka x509 certificate).
*
* The @aclname parameter (optionally) specifies the name
* of an access control list that will be used to validate
* the peer's credentials. For x509 credentials, the ACL
* will be matched against the CommonName shown in the peer's
* certificate. If the session is acting as a server, setting
* an ACL will require that the client provide a validate
* x509 client certificate.
*
* After creating the session object, the I/O callbacks
* must be set using the qcrypto_tls_session_set_callbacks()
* method. A TLS handshake sequence must then be completed
* using qcrypto_tls_session_handshake(), before payload
* data is permitted to be sent/received.
*
* The session object must be released by calling
* qcrypto_tls_session_free() when no longer required
*
* Returns: a TLS session object, or NULL on error.
*/
QCryptoTLSSession *qcrypto_tls_session_new(QCryptoTLSCreds *creds,
const char *hostname,
const char *aclname,
QCryptoTLSCredsEndpoint endpoint,
Error **errp);
/**
* qcrypto_tls_session_free:
* @sess: the TLS session object
*
* Release all memory associated with the TLS session
* object previously allocated by qcrypto_tls_session_new()
*/
void qcrypto_tls_session_free(QCryptoTLSSession *sess);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoTLSSession, qcrypto_tls_session_free)
/**
* qcrypto_tls_session_require_thread_safety:
* @sess: the TLS session object
*
* Mark that this TLS session will require thread safety
* for concurrent I/O in both directions. This must be
* called before the handshake is performed.
*
* This will activate a workaround for GNUTLS thread
* safety issues, where appropriate for the negotiated
* TLS session parameters.
*/
void qcrypto_tls_session_require_thread_safety(QCryptoTLSSession *sess);
/**
* qcrypto_tls_session_check_credentials:
* @sess: the TLS session object
* @errp: pointer to a NULL-initialized error object
*
* Validate the peer's credentials after a successful
* TLS handshake. It is an error to call this before
* qcrypto_tls_session_handshake() returns
* QCRYPTO_TLS_HANDSHAKE_COMPLETE
*
* Returns 0 if the credentials validated, -1 on error
*/
int qcrypto_tls_session_check_credentials(QCryptoTLSSession *sess,
Error **errp);
/*
* These must return QCRYPTO_TLS_SESSION_ERR_BLOCK if the I/O
* would block, but on other errors, must fill 'errp'
*/
typedef ssize_t (*QCryptoTLSSessionWriteFunc)(const void *buf,
size_t len,
void *opaque,
Error **errp);
typedef ssize_t (*QCryptoTLSSessionReadFunc)(void *buf,
size_t len,
void *opaque,
Error **errp);
/**
* qcrypto_tls_session_set_callbacks:
* @sess: the TLS session object
* @writeFunc: callback for sending data
* @readFunc: callback to receiving data
* @opaque: data to pass to callbacks
*
* Sets the callback functions that are to be used for sending
* and receiving data on the underlying data channel. Typically
* the callbacks to write/read to/from a TCP socket, but there
* is no assumption made about the type of channel used.
*
* The @writeFunc callback will be passed the encrypted
* data to send to the remote peer.
*
* The @readFunc callback will be passed a pointer to fill
* with encrypted data received from the remote peer
*/
void qcrypto_tls_session_set_callbacks(QCryptoTLSSession *sess,
QCryptoTLSSessionWriteFunc writeFunc,
QCryptoTLSSessionReadFunc readFunc,
void *opaque);
/**
* qcrypto_tls_session_write:
* @sess: the TLS session object
* @buf: the plain text to send
* @len: the length of @buf
* @errp: pointer to hold returned error object
*
* Encrypt @len bytes of the data in @buf and send
* it to the remote peer using the callback previously
* registered with qcrypto_tls_session_set_callbacks()
*
* It is an error to call this before
* qcrypto_tls_session_handshake() returns
* QCRYPTO_TLS_HANDSHAKE_COMPLETE
*
* Returns: the number of bytes sent,
* or QCRYPTO_TLS_SESSION_ERR_BLOCK if the write would block,
* or -1 on error.
*/
ssize_t qcrypto_tls_session_write(QCryptoTLSSession *sess,
const char *buf,
size_t len,
Error **errp);
/**
* qcrypto_tls_session_read:
* @sess: the TLS session object
* @buf: to fill with plain text received
* @len: the length of @buf
* @errp: pointer to hold returned error object
*
* Receive up to @len bytes of data from the remote peer
* using the callback previously registered with
* qcrypto_tls_session_set_callbacks(), decrypt it and
* store it in @buf.
*
* It is an error to call this before
* qcrypto_tls_session_handshake() returns
* QCRYPTO_TLS_HANDSHAKE_COMPLETE
*
* Returns: the number of bytes received,
* or QCRYPTO_TLS_SESSION_ERR_BLOCK if the receive would block,
* or QCRYPTO_TLS_SESSION_PREMATURE_TERMINATION if a premature termination
* is detected, or -1 on error.
*/
ssize_t qcrypto_tls_session_read(QCryptoTLSSession *sess,
char *buf,
size_t len,
Error **errp);
/**
* qcrypto_tls_session_check_pending:
* @sess: the TLS session object
*
* Check if there are unread data in the TLS buffers that have
* already been read from the underlying data source.
*
* Returns: the number of bytes available or zero
*/
size_t qcrypto_tls_session_check_pending(QCryptoTLSSession *sess);
/**
* qcrypto_tls_session_handshake:
* @sess: the TLS session object
* @errp: pointer to a NULL-initialized error object
*
* Start, or continue, a TLS handshake sequence. If
* the underlying data channel is non-blocking, then
* this method may return control before the handshake
* is complete. On non-blocking channels the
* return value determines whether the handshake
* has completed, or is waiting to send or receive
* data. In the latter cases, the caller should setup
* an event loop watch and call this method again
* once the underlying data channel is ready to read
* or write again
*/
int qcrypto_tls_session_handshake(QCryptoTLSSession *sess,
Error **errp);
typedef enum {
QCRYPTO_TLS_HANDSHAKE_COMPLETE,
QCRYPTO_TLS_HANDSHAKE_SENDING,
QCRYPTO_TLS_HANDSHAKE_RECVING,
} QCryptoTLSSessionHandshakeStatus;
typedef enum {
QCRYPTO_TLS_BYE_COMPLETE,
QCRYPTO_TLS_BYE_SENDING,
QCRYPTO_TLS_BYE_RECVING,
} QCryptoTLSSessionByeStatus;
/**
* qcrypto_tls_session_bye:
* @session: the TLS session object
* @errp: pointer to a NULL-initialized error object
*
* Start, or continue, a TLS termination sequence. If the underlying
* data channel is non-blocking, then this method may return control
* before the termination is complete. The return value will indicate
* whether the termination has completed, or is waiting to send or
* receive data. In the latter cases, the caller should setup an event
* loop watch and call this method again once the underlying data
* channel is ready to read or write again.
*/
int
qcrypto_tls_session_bye(QCryptoTLSSession *session, Error **errp);
/**
* qcrypto_tls_session_get_key_size:
* @sess: the TLS session object
* @errp: pointer to a NULL-initialized error object
*
* Check the size of the data channel encryption key
*
* Returns: the length in bytes of the encryption key
* or -1 on error
*/
int qcrypto_tls_session_get_key_size(QCryptoTLSSession *sess,
Error **errp);
/**
* qcrypto_tls_session_get_peer_name:
* @sess: the TLS session object
*
* Get the identified name of the remote peer. If the
* TLS session was negotiated using x509 certificate
* credentials, this will return the CommonName from
* the peer's certificate. If no identified name is
* available it will return NULL.
*
* The returned data must be released with g_free()
* when no longer required.
*
* Returns: the peer's name or NULL.
*/
char *qcrypto_tls_session_get_peer_name(QCryptoTLSSession *sess);
#endif /* QCRYPTO_TLSSESSION_H */
+135
View File
@@ -0,0 +1,135 @@
/*
* X.509 certificate related helpers
*
* Copyright (c) 2024 Dorjoy Chowdhury <[email protected]>
*
* This work is licensed under the terms of the GNU GPL, version 2 or
* (at your option) any later version. See the COPYING file in the
* top-level directory.
*/
#ifndef QCRYPTO_X509_UTILS_H
#define QCRYPTO_X509_UTILS_H
#include "crypto/hash.h"
int qcrypto_get_x509_cert_fingerprint(uint8_t *cert, size_t size,
QCryptoHashAlgo hash,
uint8_t *result,
size_t *resultlen,
Error **errp);
/**
* qcrypto_x509_convert_cert_der
* @cert: pointer to the raw certificate data in PEM format
* @size: size of the certificate
* @result: output location for the allocated buffer for the certificate
* in DER format
* (the function allocates memory which must be freed by the caller)
* @resultlen: pointer to the size of the buffer (will be updated with the
* actual size of the DER-encoded certificate)
* @errp: error pointer
*
* Convert the given @cert from PEM to DER format.
*
* Returns: 0 on success,
* -1 on error.
*/
int qcrypto_x509_convert_cert_der(uint8_t *cert, size_t size,
uint8_t **result,
size_t *resultlen,
Error **errp);
/**
* qcrypto_x509_check_cert_times
* @cert: pointer to the raw certificate data
* @size: size of the certificate
* @errp: error pointer
*
* Check whether the activation and expiration times of @cert
* are valid at the current time.
*
* Returns: 0 if the certificate times are valid,
* -1 on error.
*/
int qcrypto_x509_check_cert_times(uint8_t *cert, size_t size, Error **errp);
/**
* qcrypto_x509_get_cert_key_id
* @cert: pointer to the raw certificate data
* @size: size of the certificate
* @hash_alg: the hash algorithm flag
* @result: output location for the allocated buffer for key ID
* (the function allocates memory which must be freed by the caller)
* @resultlen: pointer to the size of the buffer
* (will be updated with the actual size of key id)
* @errp: error pointer
*
* Retrieve the key ID from the @cert based on the specified @hash_alg.
*
* Returns: 0 if key ID was successfully stored in @result,
* -1 on error.
*/
int qcrypto_x509_get_cert_key_id(uint8_t *cert, size_t size,
QCryptoHashAlgo hash_alg,
uint8_t **result,
size_t *resultlen,
Error **errp);
/**
* qcrypto_x509_check_ecc_curve_p521
* @cert: pointer to the raw certificate data
* @size: size of the certificate
* @errp: error pointer
*
* Determine whether the ECC public key in the given certificate uses the P-521
* curve.
*
* Returns: 0 if ECC public key does not use P521 curve.
* 1 if ECC public key uses P521 curve.
* -1 on error.
*/
int qcrypto_x509_check_ecc_curve_p521(uint8_t *cert, size_t size, Error **errp);
/**
* qcrypto_pkcs7_convert_sig_pem
* @sig: pointer to the PKCS#7 signature in DER format
* @sig_size: size of the signature
* @result: output location for the allocated buffer for the signature in
* PEM format
* (the function allocates memory which must be freed by the caller)
* @resultlen: pointer to the size of the buffer
* (will be updated with the actual size of the PEM-encoded
* signature)
* @errp: error pointer
*
* Convert given PKCS#7 @sig from DER to PEM format.
*
* Returns: 0 if PEM-encoded signature was successfully stored in @result,
* -1 on error.
*/
int qcrypto_pkcs7_convert_sig_pem(uint8_t *sig, size_t sig_size,
uint8_t **result,
size_t *resultlen,
Error **errp);
/**
* qcrypto_x509_verify_sig
* @cert: pointer to the raw certificate data
* @cert_size: size of the certificate
* @comp: pointer to the component to be verified
* @comp_size: size of the component
* @sig: pointer to the signature
* @sig_size: size of the signature
* @errp: error pointer
*
* Verify the provided @comp against the @sig and @cert.
*
* Returns: 0 on success,
* -1 on error.
*/
int qcrypto_x509_verify_sig(uint8_t *cert, size_t cert_size,
uint8_t *comp, size_t comp_size,
uint8_t *sig, size_t sig_size, Error **errp);
#endif