mirror of https://github.com/proxmox/mirror_qemu
Merge misc crypto changes & fixes
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCAAGBQJWeoF6AAoJEL6G67QVEE/ff7MP/jcF8c21q28DLPvHFTQdLCDS HsrJhUXlPBQk6knQrZQpb5PU8/s2NeyJdglzxFI7LaOlTAjlUh+bZIoU7Y9iGht9 HOKAgUX1eApkMfhpV+pzPXIrF3b7TCiWWOKsWW8SkqSnIYgigBM+8xA0XspduWvQ cSklbwvhs3duawrg8lVnRJQgbrVtDVFKrzBiUCke6qSrKqO/2iuLrpZMiv6b5uTQ tWzBb2gT/BDcZHRF6Br6DApBe1uqkL/oXmo5DtM/ouwPjuTHMnx8gYFgyIz1vbQN Ti0FrKtwrr8aK5hSnNbNcizKdst7Txw7jV5PiIDdTKV5CvYza4zdeppXXa0rSIyI ByThHzeR5J11hDiIAZ72/yHo9gIifOLqKZtQsCrRB8niyQ93rr85UWA2JWdLqRXs gbbLRK3UXwSZVWmdAlrFIZUxBUdTnc/qcLIU0cgnffC7ozZbwyjt3dnIUM6WmlxW DjY7Z5wcFbbnYsufwBZgZUhWbTj3AdAaiIdBuY33GqqtVs59nICBrtSCYmP1j4+u fDv4QlElETC5hGH9ZPeo08yGrgRA6hGlopnnKSzlfmeb62UU2aYcTW6fNP9OkZI2 HHyGa4XeaeYzYhYbbtRngSI9QjJVf5qzFq2rSFuZcf/9t0n1dztFd36DLca6sW4x fMahe7XiEmKqBBAwFaAr =fHY5 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/berrange/tags/pull-crypto-fixes-2015-12-23-1' into staging Merge misc crypto changes & fixes # gpg: Signature made Wed 23 Dec 2015 11:11:54 GMT using RSA key ID 15104FDF # gpg: Good signature from "Daniel P. Berrange <dan@berrange.com>" # gpg: aka "Daniel P. Berrange <berrange@redhat.com>" * remotes/berrange/tags/pull-crypto-fixes-2015-12-23-1: crypto: fix transposed arguments in cipher error message crypto: ensure qapi/crypto.json is listed in qapi-modules crypto: move QCryptoCipherAlgorithm/Mode enum definitions into QAPI crypto: move QCryptoHashAlgorithm enum definition into QAPI crypto: add ability to query hash digest len crypto: add additional query accessors for cipher instances Signed-off-by: Peter Maydell <peter.maydell@linaro.org>master
commit
38a762fec6
3
Makefile
3
Makefile
|
@ -271,7 +271,8 @@ $(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
|
||||||
|
|
||||||
qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
|
qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
|
||||||
$(SRC_PATH)/qapi/block.json $(SRC_PATH)/qapi/block-core.json \
|
$(SRC_PATH)/qapi/block.json $(SRC_PATH)/qapi/block-core.json \
|
||||||
$(SRC_PATH)/qapi/event.json $(SRC_PATH)/qapi/introspect.json
|
$(SRC_PATH)/qapi/event.json $(SRC_PATH)/qapi/introspect.json \
|
||||||
|
$(SRC_PATH)/qapi/crypto.json
|
||||||
|
|
||||||
qapi-types.c qapi-types.h :\
|
qapi-types.c qapi-types.h :\
|
||||||
$(qapi-modules) $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
|
$(qapi-modules) $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
|
||||||
|
|
|
@ -21,19 +21,67 @@
|
||||||
#include "crypto/cipher.h"
|
#include "crypto/cipher.h"
|
||||||
|
|
||||||
|
|
||||||
static size_t alg_key_len[QCRYPTO_CIPHER_ALG_LAST] = {
|
static size_t alg_key_len[QCRYPTO_CIPHER_ALG__MAX] = {
|
||||||
[QCRYPTO_CIPHER_ALG_AES_128] = 16,
|
[QCRYPTO_CIPHER_ALG_AES_128] = 16,
|
||||||
[QCRYPTO_CIPHER_ALG_AES_192] = 24,
|
[QCRYPTO_CIPHER_ALG_AES_192] = 24,
|
||||||
[QCRYPTO_CIPHER_ALG_AES_256] = 32,
|
[QCRYPTO_CIPHER_ALG_AES_256] = 32,
|
||||||
[QCRYPTO_CIPHER_ALG_DES_RFB] = 8,
|
[QCRYPTO_CIPHER_ALG_DES_RFB] = 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static size_t alg_block_len[QCRYPTO_CIPHER_ALG__MAX] = {
|
||||||
|
[QCRYPTO_CIPHER_ALG_AES_128] = 16,
|
||||||
|
[QCRYPTO_CIPHER_ALG_AES_192] = 16,
|
||||||
|
[QCRYPTO_CIPHER_ALG_AES_256] = 16,
|
||||||
|
[QCRYPTO_CIPHER_ALG_DES_RFB] = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool mode_need_iv[QCRYPTO_CIPHER_MODE__MAX] = {
|
||||||
|
[QCRYPTO_CIPHER_MODE_ECB] = false,
|
||||||
|
[QCRYPTO_CIPHER_MODE_CBC] = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
size_t qcrypto_cipher_get_block_len(QCryptoCipherAlgorithm alg)
|
||||||
|
{
|
||||||
|
if (alg >= G_N_ELEMENTS(alg_key_len)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return alg_block_len[alg];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t qcrypto_cipher_get_key_len(QCryptoCipherAlgorithm alg)
|
||||||
|
{
|
||||||
|
if (alg >= G_N_ELEMENTS(alg_key_len)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return alg_key_len[alg];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t qcrypto_cipher_get_iv_len(QCryptoCipherAlgorithm alg,
|
||||||
|
QCryptoCipherMode mode)
|
||||||
|
{
|
||||||
|
if (alg >= G_N_ELEMENTS(alg_block_len)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (mode >= G_N_ELEMENTS(mode_need_iv)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode_need_iv[mode]) {
|
||||||
|
return alg_block_len[alg];
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
qcrypto_cipher_validate_key_length(QCryptoCipherAlgorithm alg,
|
qcrypto_cipher_validate_key_length(QCryptoCipherAlgorithm alg,
|
||||||
size_t nkey,
|
size_t nkey,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
if ((unsigned)alg >= QCRYPTO_CIPHER_ALG_LAST) {
|
if ((unsigned)alg >= QCRYPTO_CIPHER_ALG__MAX) {
|
||||||
error_setg(errp, "Cipher algorithm %d out of range",
|
error_setg(errp, "Cipher algorithm %d out of range",
|
||||||
alg);
|
alg);
|
||||||
return false;
|
return false;
|
||||||
|
@ -41,7 +89,7 @@ qcrypto_cipher_validate_key_length(QCryptoCipherAlgorithm alg,
|
||||||
|
|
||||||
if (alg_key_len[alg] != nkey) {
|
if (alg_key_len[alg] != nkey) {
|
||||||
error_setg(errp, "Cipher key length %zu should be %zu",
|
error_setg(errp, "Cipher key length %zu should be %zu",
|
||||||
alg_key_len[alg], nkey);
|
nkey, alg_key_len[alg]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -24,12 +24,18 @@
|
||||||
#include <gnutls/gnutls.h>
|
#include <gnutls/gnutls.h>
|
||||||
#include <gnutls/crypto.h>
|
#include <gnutls/crypto.h>
|
||||||
|
|
||||||
static int qcrypto_hash_alg_map[QCRYPTO_HASH_ALG_LAST] = {
|
static int qcrypto_hash_alg_map[QCRYPTO_HASH_ALG__MAX] = {
|
||||||
[QCRYPTO_HASH_ALG_MD5] = GNUTLS_DIG_MD5,
|
[QCRYPTO_HASH_ALG_MD5] = GNUTLS_DIG_MD5,
|
||||||
[QCRYPTO_HASH_ALG_SHA1] = GNUTLS_DIG_SHA1,
|
[QCRYPTO_HASH_ALG_SHA1] = GNUTLS_DIG_SHA1,
|
||||||
[QCRYPTO_HASH_ALG_SHA256] = GNUTLS_DIG_SHA256,
|
[QCRYPTO_HASH_ALG_SHA256] = GNUTLS_DIG_SHA256,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static size_t qcrypto_hash_alg_size[QCRYPTO_HASH_ALG__MAX] = {
|
||||||
|
[QCRYPTO_HASH_ALG_MD5] = 16,
|
||||||
|
[QCRYPTO_HASH_ALG_SHA1] = 20,
|
||||||
|
[QCRYPTO_HASH_ALG_SHA256] = 32,
|
||||||
|
};
|
||||||
|
|
||||||
gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg)
|
gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg)
|
||||||
{
|
{
|
||||||
if (alg < G_N_ELEMENTS(qcrypto_hash_alg_map)) {
|
if (alg < G_N_ELEMENTS(qcrypto_hash_alg_map)) {
|
||||||
|
@ -38,6 +44,15 @@ gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t qcrypto_hash_digest_len(QCryptoHashAlgorithm alg)
|
||||||
|
{
|
||||||
|
if (alg >= G_N_ELEMENTS(qcrypto_hash_alg_size)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return qcrypto_hash_alg_size[alg];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg,
|
int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg,
|
||||||
const struct iovec *iov,
|
const struct iovec *iov,
|
||||||
size_t niov,
|
size_t niov,
|
||||||
|
|
|
@ -26,21 +26,8 @@
|
||||||
|
|
||||||
typedef struct QCryptoCipher QCryptoCipher;
|
typedef struct QCryptoCipher QCryptoCipher;
|
||||||
|
|
||||||
typedef enum {
|
/* See also "QCryptoCipherAlgorithm" and "QCryptoCipherMode"
|
||||||
QCRYPTO_CIPHER_ALG_AES_128,
|
* enums defined in qapi/crypto.json */
|
||||||
QCRYPTO_CIPHER_ALG_AES_192,
|
|
||||||
QCRYPTO_CIPHER_ALG_AES_256,
|
|
||||||
QCRYPTO_CIPHER_ALG_DES_RFB, /* A stupid variant on DES for VNC */
|
|
||||||
|
|
||||||
QCRYPTO_CIPHER_ALG_LAST
|
|
||||||
} QCryptoCipherAlgorithm;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
QCRYPTO_CIPHER_MODE_ECB,
|
|
||||||
QCRYPTO_CIPHER_MODE_CBC,
|
|
||||||
|
|
||||||
QCRYPTO_CIPHER_MODE_LAST
|
|
||||||
} QCryptoCipherMode;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* QCryptoCipher:
|
* QCryptoCipher:
|
||||||
|
@ -107,6 +94,43 @@ struct QCryptoCipher {
|
||||||
*/
|
*/
|
||||||
bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg);
|
bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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(QCryptoCipherAlgorithm 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(QCryptoCipherAlgorithm 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(QCryptoCipherAlgorithm alg,
|
||||||
|
QCryptoCipherMode mode);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qcrypto_cipher_new:
|
* qcrypto_cipher_new:
|
||||||
|
|
|
@ -24,14 +24,7 @@
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
|
|
||||||
typedef enum {
|
/* See also "QCryptoHashAlgorithm" defined in qapi/crypto.json */
|
||||||
QCRYPTO_HASH_ALG_MD5,
|
|
||||||
QCRYPTO_HASH_ALG_SHA1,
|
|
||||||
QCRYPTO_HASH_ALG_SHA256,
|
|
||||||
|
|
||||||
QCRYPTO_HASH_ALG_LAST
|
|
||||||
} QCryptoHashAlgorithm;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qcrypto_hash_supports:
|
* qcrypto_hash_supports:
|
||||||
|
@ -44,6 +37,17 @@ typedef enum {
|
||||||
*/
|
*/
|
||||||
gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg);
|
gboolean qcrypto_hash_supports(QCryptoHashAlgorithm 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(QCryptoHashAlgorithm alg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qcrypto_hash_bytesv:
|
* qcrypto_hash_bytesv:
|
||||||
* @alg: the hash algorithm
|
* @alg: the hash algorithm
|
||||||
|
|
|
@ -33,3 +33,48 @@
|
||||||
{ 'enum': 'QCryptoSecretFormat',
|
{ 'enum': 'QCryptoSecretFormat',
|
||||||
'prefix': 'QCRYPTO_SECRET_FORMAT',
|
'prefix': 'QCRYPTO_SECRET_FORMAT',
|
||||||
'data': ['raw', 'base64']}
|
'data': ['raw', 'base64']}
|
||||||
|
|
||||||
|
|
||||||
|
##
|
||||||
|
# QCryptoHashAlgorithm:
|
||||||
|
#
|
||||||
|
# The supported algorithms for computing content digests
|
||||||
|
#
|
||||||
|
# @md5: MD5. Should not be used in any new code, legacy compat only
|
||||||
|
# @sha1: SHA-1. Should not be used in any new code, legacy compat only
|
||||||
|
# @sha256: SHA-256. Current recommended strong hash.
|
||||||
|
# Since: 2.6
|
||||||
|
##
|
||||||
|
{ 'enum': 'QCryptoHashAlgorithm',
|
||||||
|
'prefix': 'QCRYPTO_HASH_ALG',
|
||||||
|
'data': ['md5', 'sha1', 'sha256']}
|
||||||
|
|
||||||
|
|
||||||
|
##
|
||||||
|
# QCryptoCipherAlgorithm:
|
||||||
|
#
|
||||||
|
# The supported algorithms for content encryption ciphers
|
||||||
|
#
|
||||||
|
# @aes-128: AES with 128 bit / 16 byte keys
|
||||||
|
# @aes-192: AES with 192 bit / 24 byte keys
|
||||||
|
# @aes-256: AES with 256 bit / 32 byte keys
|
||||||
|
# @des-rfb: RFB specific variant of single DES. Do not use except in VNC.
|
||||||
|
# Since: 2.6
|
||||||
|
##
|
||||||
|
{ 'enum': 'QCryptoCipherAlgorithm',
|
||||||
|
'prefix': 'QCRYPTO_CIPHER_ALG',
|
||||||
|
'data': ['aes-128', 'aes-192', 'aes-256', 'des-rfb']}
|
||||||
|
|
||||||
|
|
||||||
|
##
|
||||||
|
# QCryptoCipherMode:
|
||||||
|
#
|
||||||
|
# The supported modes for content encryption ciphers
|
||||||
|
#
|
||||||
|
# @ecb: Electronic Code Book
|
||||||
|
# @cbc: Cipher Block Chaining
|
||||||
|
# Since: 2.6
|
||||||
|
##
|
||||||
|
{ 'enum': 'QCryptoCipherMode',
|
||||||
|
'prefix': 'QCRYPTO_CIPHER_MODE',
|
||||||
|
'data': ['ecb', 'cbc']}
|
||||||
|
|
|
@ -229,6 +229,7 @@ static void test_cipher(const void *opaque)
|
||||||
uint8_t *key, *iv, *ciphertext, *plaintext, *outtext;
|
uint8_t *key, *iv, *ciphertext, *plaintext, *outtext;
|
||||||
size_t nkey, niv, nciphertext, nplaintext;
|
size_t nkey, niv, nciphertext, nplaintext;
|
||||||
char *outtexthex;
|
char *outtexthex;
|
||||||
|
size_t ivsize, keysize, blocksize;
|
||||||
|
|
||||||
nkey = unhex_string(data->key, &key);
|
nkey = unhex_string(data->key, &key);
|
||||||
niv = unhex_string(data->iv, &iv);
|
niv = unhex_string(data->iv, &iv);
|
||||||
|
@ -245,6 +246,15 @@ static void test_cipher(const void *opaque)
|
||||||
&error_abort);
|
&error_abort);
|
||||||
g_assert(cipher != NULL);
|
g_assert(cipher != NULL);
|
||||||
|
|
||||||
|
keysize = qcrypto_cipher_get_key_len(data->alg);
|
||||||
|
blocksize = qcrypto_cipher_get_block_len(data->alg);
|
||||||
|
ivsize = qcrypto_cipher_get_iv_len(data->alg, data->mode);
|
||||||
|
|
||||||
|
g_assert_cmpint(keysize, ==, nkey);
|
||||||
|
g_assert_cmpint(ivsize, ==, niv);
|
||||||
|
if (niv) {
|
||||||
|
g_assert_cmpint(blocksize, ==, niv);
|
||||||
|
}
|
||||||
|
|
||||||
if (iv) {
|
if (iv) {
|
||||||
g_assert(qcrypto_cipher_setiv(cipher,
|
g_assert(qcrypto_cipher_setiv(cipher,
|
||||||
|
|
|
@ -163,6 +163,11 @@ static void test_hash_digest(void)
|
||||||
for (i = 0; i < G_N_ELEMENTS(expected_outputs) ; i++) {
|
for (i = 0; i < G_N_ELEMENTS(expected_outputs) ; i++) {
|
||||||
int ret;
|
int ret;
|
||||||
char *digest;
|
char *digest;
|
||||||
|
size_t digestsize;
|
||||||
|
|
||||||
|
digestsize = qcrypto_hash_digest_len(i);
|
||||||
|
|
||||||
|
g_assert_cmpint(digestsize * 2, ==, strlen(expected_outputs[i]));
|
||||||
|
|
||||||
ret = qcrypto_hash_digest(i,
|
ret = qcrypto_hash_digest(i,
|
||||||
INPUT_TEXT,
|
INPUT_TEXT,
|
||||||
|
|
Loading…
Reference in New Issue