qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

Merge remote-tracking branch 'remotes/berrange/tags/pull-qcrypto-2016-12-21-2' into staging

Merge qcrypto 2016/12/21 v2

# gpg: Signature made Thu 22 Dec 2016 10:46:17 GMT
# gpg: using RSA key 0xBE86EBB415104FDF
# gpg: Good signature from "Daniel P. Berrange <dan@berrange.com>"
# gpg: aka "Daniel P. Berrange <berrange@redhat.com>"
# Primary key fingerprint: DAF3 A6FD B26B 6291 2D0E 8E3F BE86 EBB4 1510 4FDF

* remotes/berrange/tags/pull-qcrypto-2016-12-21-2:
crypto: add HMAC algorithms testcases
crypto: support HMAC algorithms based on nettle
crypto: support HMAC algorithms based on glib
crypto: support HMAC algorithms based on libgcrypt
crypto: add HMAC algorithms framework
configure: add CONFIG_GCRYPT_HMAC item
crypto: add 3des-ede support when using libgcrypt/nettle
cipher: fix leak on initialization error

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

+1191 -6
+17
configure
··· 313 313 nettle="" 314 314 nettle_kdf="no" 315 315 gcrypt="" 316 + gcrypt_hmac="no" 316 317 gcrypt_kdf="no" 317 318 vte="" 318 319 virglrenderer="" ··· 2416 2417 EOF 2417 2418 if compile_prog "$gcrypt_cflags" "$gcrypt_libs" ; then 2418 2419 gcrypt_kdf=yes 2420 + fi 2421 + 2422 + cat > $TMPC << EOF 2423 + #include <gcrypt.h> 2424 + int main(void) { 2425 + gcry_mac_hd_t handle; 2426 + gcry_mac_open(&handle, GCRY_MAC_HMAC_MD5, 2427 + GCRY_MAC_FLAG_SECURE, NULL); 2428 + return 0; 2429 + } 2430 + EOF 2431 + if compile_prog "$gcrypt_cflags" "$gcrypt_libs" ; then 2432 + gcrypt_hmac=yes 2419 2433 fi 2420 2434 else 2421 2435 if test "$gcrypt" = "yes"; then ··· 5387 5401 fi 5388 5402 if test "$gcrypt" = "yes" ; then 5389 5403 echo "CONFIG_GCRYPT=y" >> $config_host_mak 5404 + if test "$gcrypt_hmac" = "yes" ; then 5405 + echo "CONFIG_GCRYPT_HMAC=y" >> $config_host_mak 5406 + fi 5390 5407 if test "$gcrypt_kdf" = "yes" ; then 5391 5408 echo "CONFIG_GCRYPT_KDF=y" >> $config_host_mak 5392 5409 fi
+4
crypto/Makefile.objs
··· 3 3 crypto-obj-$(CONFIG_NETTLE) += hash-nettle.o 4 4 crypto-obj-$(if $(CONFIG_NETTLE),n,$(CONFIG_GCRYPT)) += hash-gcrypt.o 5 5 crypto-obj-$(if $(CONFIG_NETTLE),n,$(if $(CONFIG_GCRYPT),n,y)) += hash-glib.o 6 + crypto-obj-y += hmac.o 7 + crypto-obj-$(CONFIG_NETTLE) += hmac-nettle.o 8 + crypto-obj-$(CONFIG_GCRYPT_HMAC) += hmac-gcrypt.o 9 + crypto-obj-$(if $(CONFIG_NETTLE),n,$(if $(CONFIG_GCRYPT_HMAC),n,y)) += hmac-glib.o 6 10 crypto-obj-y += aes.o 7 11 crypto-obj-y += desrfb.o 8 12 crypto-obj-y += cipher.o
+6
crypto/cipher-gcrypt.c
··· 29 29 { 30 30 switch (alg) { 31 31 case QCRYPTO_CIPHER_ALG_DES_RFB: 32 + case QCRYPTO_CIPHER_ALG_3DES: 32 33 case QCRYPTO_CIPHER_ALG_AES_128: 33 34 case QCRYPTO_CIPHER_ALG_AES_192: 34 35 case QCRYPTO_CIPHER_ALG_AES_256: ··· 97 98 switch (alg) { 98 99 case QCRYPTO_CIPHER_ALG_DES_RFB: 99 100 gcryalg = GCRY_CIPHER_DES; 101 + break; 102 + 103 + case QCRYPTO_CIPHER_ALG_3DES: 104 + gcryalg = GCRY_CIPHER_3DES; 100 105 break; 101 106 102 107 case QCRYPTO_CIPHER_ALG_AES_128: ··· 200 205 case QCRYPTO_CIPHER_ALG_TWOFISH_256: 201 206 ctx->blocksize = 16; 202 207 break; 208 + case QCRYPTO_CIPHER_ALG_3DES: 203 209 case QCRYPTO_CIPHER_ALG_CAST5_128: 204 210 ctx->blocksize = 8; 205 211 break;
+39 -3
crypto/cipher-nettle.c
··· 78 78 des_decrypt(ctx, length, dst, src); 79 79 } 80 80 81 + static void des3_encrypt_native(cipher_ctx_t ctx, cipher_length_t length, 82 + uint8_t *dst, const uint8_t *src) 83 + { 84 + des3_encrypt(ctx, length, dst, src); 85 + } 86 + 87 + static void des3_decrypt_native(cipher_ctx_t ctx, cipher_length_t length, 88 + uint8_t *dst, const uint8_t *src) 89 + { 90 + des3_decrypt(ctx, length, dst, src); 91 + } 92 + 81 93 static void cast128_encrypt_native(cipher_ctx_t ctx, cipher_length_t length, 82 94 uint8_t *dst, const uint8_t *src) 83 95 { ··· 140 152 des_decrypt(ctx, length, dst, src); 141 153 } 142 154 155 + static void des3_encrypt_wrapper(const void *ctx, size_t length, 156 + uint8_t *dst, const uint8_t *src) 157 + { 158 + des3_encrypt(ctx, length, dst, src); 159 + } 160 + 161 + static void des3_decrypt_wrapper(const void *ctx, size_t length, 162 + uint8_t *dst, const uint8_t *src) 163 + { 164 + des3_decrypt(ctx, length, dst, src); 165 + } 166 + 143 167 static void cast128_encrypt_wrapper(const void *ctx, size_t length, 144 168 uint8_t *dst, const uint8_t *src) 145 169 { ··· 197 221 { 198 222 switch (alg) { 199 223 case QCRYPTO_CIPHER_ALG_DES_RFB: 224 + case QCRYPTO_CIPHER_ALG_3DES: 200 225 case QCRYPTO_CIPHER_ALG_AES_128: 201 226 case QCRYPTO_CIPHER_ALG_AES_192: 202 227 case QCRYPTO_CIPHER_ALG_AES_256: ··· 254 279 cipher->mode = mode; 255 280 256 281 ctx = g_new0(QCryptoCipherNettle, 1); 282 + cipher->opaque = ctx; 257 283 258 284 switch (alg) { 259 285 case QCRYPTO_CIPHER_ALG_DES_RFB: ··· 270 296 ctx->blocksize = DES_BLOCK_SIZE; 271 297 break; 272 298 299 + case QCRYPTO_CIPHER_ALG_3DES: 300 + ctx->ctx = g_new0(struct des3_ctx, 1); 301 + des3_set_key(ctx->ctx, key); 302 + 303 + ctx->alg_encrypt_native = des3_encrypt_native; 304 + ctx->alg_decrypt_native = des3_decrypt_native; 305 + ctx->alg_encrypt_wrapper = des3_encrypt_wrapper; 306 + ctx->alg_decrypt_wrapper = des3_decrypt_wrapper; 307 + 308 + ctx->blocksize = DES3_BLOCK_SIZE; 309 + break; 310 + 273 311 case QCRYPTO_CIPHER_ALG_AES_128: 274 312 case QCRYPTO_CIPHER_ALG_AES_192: 275 313 case QCRYPTO_CIPHER_ALG_AES_256: ··· 384 422 } 385 423 386 424 ctx->iv = g_new0(uint8_t, ctx->blocksize); 387 - cipher->opaque = ctx; 388 425 389 426 return cipher; 390 427 391 428 error: 392 - g_free(cipher); 393 - g_free(ctx); 429 + qcrypto_cipher_free(cipher); 394 430 return NULL; 395 431 } 396 432
+5 -2
crypto/cipher.c
··· 28 28 [QCRYPTO_CIPHER_ALG_AES_192] = 24, 29 29 [QCRYPTO_CIPHER_ALG_AES_256] = 32, 30 30 [QCRYPTO_CIPHER_ALG_DES_RFB] = 8, 31 + [QCRYPTO_CIPHER_ALG_3DES] = 24, 31 32 [QCRYPTO_CIPHER_ALG_CAST5_128] = 16, 32 33 [QCRYPTO_CIPHER_ALG_SERPENT_128] = 16, 33 34 [QCRYPTO_CIPHER_ALG_SERPENT_192] = 24, ··· 42 43 [QCRYPTO_CIPHER_ALG_AES_192] = 16, 43 44 [QCRYPTO_CIPHER_ALG_AES_256] = 16, 44 45 [QCRYPTO_CIPHER_ALG_DES_RFB] = 8, 46 + [QCRYPTO_CIPHER_ALG_3DES] = 8, 45 47 [QCRYPTO_CIPHER_ALG_CAST5_128] = 8, 46 48 [QCRYPTO_CIPHER_ALG_SERPENT_128] = 16, 47 49 [QCRYPTO_CIPHER_ALG_SERPENT_192] = 16, ··· 107 109 } 108 110 109 111 if (mode == QCRYPTO_CIPHER_MODE_XTS) { 110 - if (alg == QCRYPTO_CIPHER_ALG_DES_RFB) { 111 - error_setg(errp, "XTS mode not compatible with DES-RFB"); 112 + if (alg == QCRYPTO_CIPHER_ALG_DES_RFB 113 + || alg == QCRYPTO_CIPHER_ALG_3DES) { 114 + error_setg(errp, "XTS mode not compatible with DES-RFB/3DES"); 112 115 return false; 113 116 } 114 117 if (nkey % 2) {
+152
crypto/hmac-gcrypt.c
··· 1 + /* 2 + * QEMU Crypto hmac algorithms (based on libgcrypt) 3 + * 4 + * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD. 5 + * 6 + * Authors: 7 + * Longpeng(Mike) <longpeng2@huawei.com> 8 + * 9 + * This work is licensed under the terms of the GNU GPL, version 2 or 10 + * (at your option) any later version. See the COPYING file in the 11 + * top-level directory. 12 + * 13 + */ 14 + 15 + #include "qemu/osdep.h" 16 + #include "qapi/error.h" 17 + #include "crypto/hmac.h" 18 + #include <gcrypt.h> 19 + 20 + static int qcrypto_hmac_alg_map[QCRYPTO_HASH_ALG__MAX] = { 21 + [QCRYPTO_HASH_ALG_MD5] = GCRY_MAC_HMAC_MD5, 22 + [QCRYPTO_HASH_ALG_SHA1] = GCRY_MAC_HMAC_SHA1, 23 + [QCRYPTO_HASH_ALG_SHA224] = GCRY_MAC_HMAC_SHA224, 24 + [QCRYPTO_HASH_ALG_SHA256] = GCRY_MAC_HMAC_SHA256, 25 + [QCRYPTO_HASH_ALG_SHA384] = GCRY_MAC_HMAC_SHA384, 26 + [QCRYPTO_HASH_ALG_SHA512] = GCRY_MAC_HMAC_SHA512, 27 + [QCRYPTO_HASH_ALG_RIPEMD160] = GCRY_MAC_HMAC_RMD160, 28 + }; 29 + 30 + typedef struct QCryptoHmacGcrypt QCryptoHmacGcrypt; 31 + struct QCryptoHmacGcrypt { 32 + gcry_mac_hd_t handle; 33 + }; 34 + 35 + bool qcrypto_hmac_supports(QCryptoHashAlgorithm alg) 36 + { 37 + if (alg < G_N_ELEMENTS(qcrypto_hmac_alg_map) && 38 + qcrypto_hmac_alg_map[alg] != GCRY_MAC_NONE) { 39 + return true; 40 + } 41 + 42 + return false; 43 + } 44 + 45 + QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg, 46 + const uint8_t *key, size_t nkey, 47 + Error **errp) 48 + { 49 + QCryptoHmac *hmac; 50 + QCryptoHmacGcrypt *ctx; 51 + gcry_error_t err; 52 + 53 + if (!qcrypto_hmac_supports(alg)) { 54 + error_setg(errp, "Unsupported hmac algorithm %s", 55 + QCryptoHashAlgorithm_lookup[alg]); 56 + return NULL; 57 + } 58 + 59 + hmac = g_new0(QCryptoHmac, 1); 60 + hmac->alg = alg; 61 + 62 + ctx = g_new0(QCryptoHmacGcrypt, 1); 63 + 64 + err = gcry_mac_open(&ctx->handle, qcrypto_hmac_alg_map[alg], 65 + GCRY_MAC_FLAG_SECURE, NULL); 66 + if (err != 0) { 67 + error_setg(errp, "Cannot initialize hmac: %s", 68 + gcry_strerror(err)); 69 + goto error; 70 + } 71 + 72 + err = gcry_mac_setkey(ctx->handle, (const void *)key, nkey); 73 + if (err != 0) { 74 + error_setg(errp, "Cannot set key: %s", 75 + gcry_strerror(err)); 76 + goto error; 77 + } 78 + 79 + hmac->opaque = ctx; 80 + return hmac; 81 + 82 + error: 83 + g_free(ctx); 84 + g_free(hmac); 85 + return NULL; 86 + } 87 + 88 + void qcrypto_hmac_free(QCryptoHmac *hmac) 89 + { 90 + QCryptoHmacGcrypt *ctx; 91 + 92 + if (!hmac) { 93 + return; 94 + } 95 + 96 + ctx = hmac->opaque; 97 + gcry_mac_close(ctx->handle); 98 + 99 + g_free(ctx); 100 + g_free(hmac); 101 + } 102 + 103 + int qcrypto_hmac_bytesv(QCryptoHmac *hmac, 104 + const struct iovec *iov, 105 + size_t niov, 106 + uint8_t **result, 107 + size_t *resultlen, 108 + Error **errp) 109 + { 110 + QCryptoHmacGcrypt *ctx; 111 + gcry_error_t err; 112 + uint32_t ret; 113 + int i; 114 + 115 + ctx = hmac->opaque; 116 + 117 + for (i = 0; i < niov; i++) { 118 + gcry_mac_write(ctx->handle, iov[i].iov_base, iov[i].iov_len); 119 + } 120 + 121 + ret = gcry_mac_get_algo_maclen(qcrypto_hmac_alg_map[hmac->alg]); 122 + if (ret <= 0) { 123 + error_setg(errp, "Unable to get hmac length: %s", 124 + gcry_strerror(ret)); 125 + return -1; 126 + } 127 + 128 + if (*resultlen == 0) { 129 + *resultlen = ret; 130 + *result = g_new0(uint8_t, *resultlen); 131 + } else if (*resultlen != ret) { 132 + error_setg(errp, "Result buffer size %zu is smaller than hmac %d", 133 + *resultlen, ret); 134 + return -1; 135 + } 136 + 137 + err = gcry_mac_read(ctx->handle, *result, resultlen); 138 + if (err != 0) { 139 + error_setg(errp, "Cannot get result: %s", 140 + gcry_strerror(err)); 141 + return -1; 142 + } 143 + 144 + err = gcry_mac_reset(ctx->handle); 145 + if (err != 0) { 146 + error_setg(errp, "Cannot reset hmac context: %s", 147 + gcry_strerror(err)); 148 + return -1; 149 + } 150 + 151 + return 0; 152 + }
+166
crypto/hmac-glib.c
··· 1 + /* 2 + * QEMU Crypto hmac algorithms (based on glib) 3 + * 4 + * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD. 5 + * 6 + * Authors: 7 + * Longpeng(Mike) <longpeng2@huawei.com> 8 + * 9 + * This work is licensed under the terms of the GNU GPL, version 2 or 10 + * (at your option) any later version. See the COPYING file in the 11 + * top-level directory. 12 + * 13 + */ 14 + 15 + #include "qemu/osdep.h" 16 + #include "qapi/error.h" 17 + #include "crypto/hmac.h" 18 + 19 + /* Support for HMAC Algos has been added in GLib 2.30 */ 20 + #if GLIB_CHECK_VERSION(2, 30, 0) 21 + 22 + static int qcrypto_hmac_alg_map[QCRYPTO_HASH_ALG__MAX] = { 23 + [QCRYPTO_HASH_ALG_MD5] = G_CHECKSUM_MD5, 24 + [QCRYPTO_HASH_ALG_SHA1] = G_CHECKSUM_SHA1, 25 + [QCRYPTO_HASH_ALG_SHA256] = G_CHECKSUM_SHA256, 26 + /* Support for HMAC SHA-512 in GLib 2.42 */ 27 + #if GLIB_CHECK_VERSION(2, 42, 0) 28 + [QCRYPTO_HASH_ALG_SHA512] = G_CHECKSUM_SHA512, 29 + #else 30 + [QCRYPTO_HASH_ALG_SHA512] = -1, 31 + #endif 32 + [QCRYPTO_HASH_ALG_SHA224] = -1, 33 + [QCRYPTO_HASH_ALG_SHA384] = -1, 34 + [QCRYPTO_HASH_ALG_RIPEMD160] = -1, 35 + }; 36 + 37 + typedef struct QCryptoHmacGlib QCryptoHmacGlib; 38 + struct QCryptoHmacGlib { 39 + GHmac *ghmac; 40 + }; 41 + 42 + bool qcrypto_hmac_supports(QCryptoHashAlgorithm alg) 43 + { 44 + if (alg < G_N_ELEMENTS(qcrypto_hmac_alg_map) && 45 + qcrypto_hmac_alg_map[alg] != -1) { 46 + return true; 47 + } 48 + 49 + return false; 50 + } 51 + 52 + QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg, 53 + const uint8_t *key, size_t nkey, 54 + Error **errp) 55 + { 56 + QCryptoHmac *hmac; 57 + QCryptoHmacGlib *ctx; 58 + 59 + if (!qcrypto_hmac_supports(alg)) { 60 + error_setg(errp, "Unsupported hmac algorithm %s", 61 + QCryptoHashAlgorithm_lookup[alg]); 62 + return NULL; 63 + } 64 + 65 + hmac = g_new0(QCryptoHmac, 1); 66 + hmac->alg = alg; 67 + 68 + ctx = g_new0(QCryptoHmacGlib, 1); 69 + 70 + ctx->ghmac = g_hmac_new(qcrypto_hmac_alg_map[alg], 71 + (const uint8_t *)key, nkey); 72 + if (!ctx->ghmac) { 73 + error_setg(errp, "Cannot initialize hmac and set key"); 74 + goto error; 75 + } 76 + 77 + hmac->opaque = ctx; 78 + return hmac; 79 + 80 + error: 81 + g_free(ctx); 82 + g_free(hmac); 83 + return NULL; 84 + } 85 + 86 + void qcrypto_hmac_free(QCryptoHmac *hmac) 87 + { 88 + QCryptoHmacGlib *ctx; 89 + 90 + if (!hmac) { 91 + return; 92 + } 93 + 94 + ctx = hmac->opaque; 95 + g_hmac_unref(ctx->ghmac); 96 + 97 + g_free(ctx); 98 + g_free(hmac); 99 + } 100 + 101 + int qcrypto_hmac_bytesv(QCryptoHmac *hmac, 102 + const struct iovec *iov, 103 + size_t niov, 104 + uint8_t **result, 105 + size_t *resultlen, 106 + Error **errp) 107 + { 108 + QCryptoHmacGlib *ctx; 109 + int i, ret; 110 + 111 + ctx = hmac->opaque; 112 + 113 + for (i = 0; i < niov; i++) { 114 + g_hmac_update(ctx->ghmac, iov[i].iov_base, iov[i].iov_len); 115 + } 116 + 117 + ret = g_checksum_type_get_length(qcrypto_hmac_alg_map[hmac->alg]); 118 + if (ret < 0) { 119 + error_setg(errp, "Unable to get hmac length"); 120 + return -1; 121 + } 122 + 123 + if (*resultlen == 0) { 124 + *resultlen = ret; 125 + *result = g_new0(uint8_t, *resultlen); 126 + } else if (*resultlen != ret) { 127 + error_setg(errp, "Result buffer size %zu is smaller than hmac %d", 128 + *resultlen, ret); 129 + return -1; 130 + } 131 + 132 + g_hmac_get_digest(ctx->ghmac, *result, resultlen); 133 + 134 + return 0; 135 + } 136 + 137 + #else 138 + 139 + bool qcrypto_hmac_supports(QCryptoHashAlgorithm alg) 140 + { 141 + return false; 142 + } 143 + 144 + QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg, 145 + const uint8_t *key, size_t nkey, 146 + Error **errp) 147 + { 148 + return NULL; 149 + } 150 + 151 + void qcrypto_hmac_free(QCryptoHmac *hmac) 152 + { 153 + return; 154 + } 155 + 156 + int qcrypto_hmac_bytesv(QCryptoHmac *hmac, 157 + const struct iovec *iov, 158 + size_t niov, 159 + uint8_t **result, 160 + size_t *resultlen, 161 + Error **errp) 162 + { 163 + return -1; 164 + } 165 + 166 + #endif
+175
crypto/hmac-nettle.c
··· 1 + /* 2 + * QEMU Crypto hmac algorithms (based on nettle) 3 + * 4 + * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD. 5 + * 6 + * Authors: 7 + * Longpeng(Mike) <longpeng2@huawei.com> 8 + * 9 + * This work is licensed under the terms of the GNU GPL, version 2 or 10 + * (at your option) any later version. See the COPYING file in the 11 + * top-level directory. 12 + * 13 + */ 14 + 15 + #include "qemu/osdep.h" 16 + #include "qapi/error.h" 17 + #include "crypto/hmac.h" 18 + #include <nettle/hmac.h> 19 + 20 + typedef void (*qcrypto_nettle_hmac_setkey)(void *ctx, 21 + size_t key_length, const uint8_t *key); 22 + 23 + typedef void (*qcrypto_nettle_hmac_update)(void *ctx, 24 + size_t length, const uint8_t *data); 25 + 26 + typedef void (*qcrypto_nettle_hmac_digest)(void *ctx, 27 + size_t length, uint8_t *digest); 28 + 29 + typedef struct QCryptoHmacNettle QCryptoHmacNettle; 30 + struct QCryptoHmacNettle { 31 + union qcrypto_nettle_hmac_ctx { 32 + struct hmac_md5_ctx md5_ctx; 33 + struct hmac_sha1_ctx sha1_ctx; 34 + struct hmac_sha256_ctx sha256_ctx; /* equals hmac_sha224_ctx */ 35 + struct hmac_sha512_ctx sha512_ctx; /* equals hmac_sha384_ctx */ 36 + struct hmac_ripemd160_ctx ripemd160_ctx; 37 + } u; 38 + }; 39 + 40 + struct qcrypto_nettle_hmac_alg { 41 + qcrypto_nettle_hmac_setkey setkey; 42 + qcrypto_nettle_hmac_update update; 43 + qcrypto_nettle_hmac_digest digest; 44 + size_t len; 45 + } qcrypto_hmac_alg_map[QCRYPTO_HASH_ALG__MAX] = { 46 + [QCRYPTO_HASH_ALG_MD5] = { 47 + .setkey = (qcrypto_nettle_hmac_setkey)hmac_md5_set_key, 48 + .update = (qcrypto_nettle_hmac_update)hmac_md5_update, 49 + .digest = (qcrypto_nettle_hmac_digest)hmac_md5_digest, 50 + .len = MD5_DIGEST_SIZE, 51 + }, 52 + [QCRYPTO_HASH_ALG_SHA1] = { 53 + .setkey = (qcrypto_nettle_hmac_setkey)hmac_sha1_set_key, 54 + .update = (qcrypto_nettle_hmac_update)hmac_sha1_update, 55 + .digest = (qcrypto_nettle_hmac_digest)hmac_sha1_digest, 56 + .len = SHA1_DIGEST_SIZE, 57 + }, 58 + [QCRYPTO_HASH_ALG_SHA224] = { 59 + .setkey = (qcrypto_nettle_hmac_setkey)hmac_sha224_set_key, 60 + .update = (qcrypto_nettle_hmac_update)hmac_sha224_update, 61 + .digest = (qcrypto_nettle_hmac_digest)hmac_sha224_digest, 62 + .len = SHA224_DIGEST_SIZE, 63 + }, 64 + [QCRYPTO_HASH_ALG_SHA256] = { 65 + .setkey = (qcrypto_nettle_hmac_setkey)hmac_sha256_set_key, 66 + .update = (qcrypto_nettle_hmac_update)hmac_sha256_update, 67 + .digest = (qcrypto_nettle_hmac_digest)hmac_sha256_digest, 68 + .len = SHA256_DIGEST_SIZE, 69 + }, 70 + [QCRYPTO_HASH_ALG_SHA384] = { 71 + .setkey = (qcrypto_nettle_hmac_setkey)hmac_sha384_set_key, 72 + .update = (qcrypto_nettle_hmac_update)hmac_sha384_update, 73 + .digest = (qcrypto_nettle_hmac_digest)hmac_sha384_digest, 74 + .len = SHA384_DIGEST_SIZE, 75 + }, 76 + [QCRYPTO_HASH_ALG_SHA512] = { 77 + .setkey = (qcrypto_nettle_hmac_setkey)hmac_sha512_set_key, 78 + .update = (qcrypto_nettle_hmac_update)hmac_sha512_update, 79 + .digest = (qcrypto_nettle_hmac_digest)hmac_sha512_digest, 80 + .len = SHA512_DIGEST_SIZE, 81 + }, 82 + [QCRYPTO_HASH_ALG_RIPEMD160] = { 83 + .setkey = (qcrypto_nettle_hmac_setkey)hmac_ripemd160_set_key, 84 + .update = (qcrypto_nettle_hmac_update)hmac_ripemd160_update, 85 + .digest = (qcrypto_nettle_hmac_digest)hmac_ripemd160_digest, 86 + .len = RIPEMD160_DIGEST_SIZE, 87 + }, 88 + }; 89 + 90 + bool qcrypto_hmac_supports(QCryptoHashAlgorithm alg) 91 + { 92 + if (alg < G_N_ELEMENTS(qcrypto_hmac_alg_map) && 93 + qcrypto_hmac_alg_map[alg].setkey != NULL) { 94 + return true; 95 + } 96 + 97 + return false; 98 + } 99 + 100 + QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg, 101 + const uint8_t *key, size_t nkey, 102 + Error **errp) 103 + { 104 + QCryptoHmac *hmac; 105 + QCryptoHmacNettle *ctx; 106 + 107 + if (!qcrypto_hmac_supports(alg)) { 108 + error_setg(errp, "Unsupported hmac algorithm %s", 109 + QCryptoHashAlgorithm_lookup[alg]); 110 + return NULL; 111 + } 112 + 113 + hmac = g_new0(QCryptoHmac, 1); 114 + hmac->alg = alg; 115 + 116 + ctx = g_new0(QCryptoHmacNettle, 1); 117 + 118 + qcrypto_hmac_alg_map[alg].setkey(&ctx->u, nkey, key); 119 + 120 + hmac->opaque = ctx; 121 + 122 + return hmac; 123 + } 124 + 125 + void qcrypto_hmac_free(QCryptoHmac *hmac) 126 + { 127 + QCryptoHmacNettle *ctx; 128 + 129 + if (!hmac) { 130 + return; 131 + } 132 + 133 + ctx = hmac->opaque; 134 + 135 + g_free(ctx); 136 + g_free(hmac); 137 + } 138 + 139 + int qcrypto_hmac_bytesv(QCryptoHmac *hmac, 140 + const struct iovec *iov, 141 + size_t niov, 142 + uint8_t **result, 143 + size_t *resultlen, 144 + Error **errp) 145 + { 146 + QCryptoHmacNettle *ctx; 147 + int i; 148 + 149 + ctx = (QCryptoHmacNettle *)hmac->opaque; 150 + 151 + for (i = 0; i < niov; ++i) { 152 + size_t len = iov[i].iov_len; 153 + uint8_t *base = iov[i].iov_base; 154 + while (len) { 155 + size_t shortlen = MIN(len, UINT_MAX); 156 + qcrypto_hmac_alg_map[hmac->alg].update(&ctx->u, len, base); 157 + len -= shortlen; 158 + base += len; 159 + } 160 + } 161 + 162 + if (*resultlen == 0) { 163 + *resultlen = qcrypto_hmac_alg_map[hmac->alg].len; 164 + *result = g_new0(uint8_t, *resultlen); 165 + } else if (*resultlen != qcrypto_hmac_alg_map[hmac->alg].len) { 166 + error_setg(errp, 167 + "Result buffer size %zu is smaller than hash %zu", 168 + *resultlen, qcrypto_hmac_alg_map[hmac->alg].len); 169 + return -1; 170 + } 171 + 172 + qcrypto_hmac_alg_map[hmac->alg].digest(&ctx->u, *resultlen, *result); 173 + 174 + return 0; 175 + }
+72
crypto/hmac.c
··· 1 + /* 2 + * QEMU Crypto hmac algorithms 3 + * 4 + * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD. 5 + * 6 + * This work is licensed under the terms of the GNU GPL, version 2 or 7 + * (at your option) any later version. See the COPYING file in the 8 + * top-level directory. 9 + * 10 + */ 11 + 12 + #include "qemu/osdep.h" 13 + #include "qapi/error.h" 14 + #include "crypto/hmac.h" 15 + 16 + static const char hex[] = "0123456789abcdef"; 17 + 18 + int qcrypto_hmac_bytes(QCryptoHmac *hmac, 19 + const char *buf, 20 + size_t len, 21 + uint8_t **result, 22 + size_t *resultlen, 23 + Error **errp) 24 + { 25 + struct iovec iov = { 26 + .iov_base = (char *)buf, 27 + .iov_len = len 28 + }; 29 + 30 + return qcrypto_hmac_bytesv(hmac, &iov, 1, result, resultlen, errp); 31 + } 32 + 33 + int qcrypto_hmac_digestv(QCryptoHmac *hmac, 34 + const struct iovec *iov, 35 + size_t niov, 36 + char **digest, 37 + Error **errp) 38 + { 39 + uint8_t *result = NULL; 40 + size_t resultlen = 0; 41 + size_t i; 42 + 43 + if (qcrypto_hmac_bytesv(hmac, iov, niov, &result, &resultlen, errp) < 0) { 44 + return -1; 45 + } 46 + 47 + *digest = g_new0(char, (resultlen * 2) + 1); 48 + 49 + for (i = 0 ; i < resultlen ; i++) { 50 + (*digest)[(i * 2)] = hex[(result[i] >> 4) & 0xf]; 51 + (*digest)[(i * 2) + 1] = hex[result[i] & 0xf]; 52 + } 53 + 54 + (*digest)[resultlen * 2] = '\0'; 55 + 56 + g_free(result); 57 + return 0; 58 + } 59 + 60 + int qcrypto_hmac_digest(QCryptoHmac *hmac, 61 + const char *buf, 62 + size_t len, 63 + char **digest, 64 + Error **errp) 65 + { 66 + struct iovec iov = { 67 + .iov_base = (char *)buf, 68 + .iov_len = len 69 + }; 70 + 71 + return qcrypto_hmac_digestv(hmac, &iov, 1, digest, errp); 72 + }
+166
crypto/hmac.h
··· 1 + /* 2 + * QEMU Crypto hmac algorithms 3 + * 4 + * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD. 5 + * 6 + * This work is licensed under the terms of the GNU GPL, version 2 or 7 + * (at your option) any later version. See the COPYING file in the 8 + * top-level directory. 9 + * 10 + */ 11 + 12 + #ifndef QCRYPTO_HMAC_H 13 + #define QCRYPTO_HMAC_H 14 + 15 + #include "qapi-types.h" 16 + 17 + typedef struct QCryptoHmac QCryptoHmac; 18 + struct QCryptoHmac { 19 + QCryptoHashAlgorithm alg; 20 + void *opaque; 21 + }; 22 + 23 + /** 24 + * qcrypto_hmac_supports: 25 + * @alg: the hmac algorithm 26 + * 27 + * Determine if @alg hmac algorithm is supported by 28 + * the current configured build 29 + * 30 + * Returns: 31 + * true if the algorithm is supported, false otherwise 32 + */ 33 + bool qcrypto_hmac_supports(QCryptoHashAlgorithm alg); 34 + 35 + /** 36 + * qcrypto_hmac_new: 37 + * @alg: the hmac algorithm 38 + * @key: the key bytes 39 + * @nkey: the length of @key 40 + * @errp: pointer to a NULL-initialized error object 41 + * 42 + * Creates a new hmac object with the algorithm @alg 43 + * 44 + * The @key parameter provides the bytes representing 45 + * the secret key to use. The @nkey parameter specifies 46 + * the length of @key in bytes 47 + * 48 + * Note: must use qcrypto_hmac_free() to release the 49 + * returned hmac object when no longer required 50 + * 51 + * Returns: 52 + * a new hmac object, or NULL on error 53 + */ 54 + QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg, 55 + const uint8_t *key, size_t nkey, 56 + Error **errp); 57 + 58 + /** 59 + * qcrypto_hmac_free: 60 + * @hmac: the hmac object 61 + * 62 + * Release the memory associated with @hmac that was 63 + * previously allocated by qcrypto_hmac_new() 64 + */ 65 + void qcrypto_hmac_free(QCryptoHmac *hmac); 66 + 67 + /** 68 + * qcrypto_hmac_bytesv: 69 + * @hmac: the hmac object 70 + * @iov: the array of memory regions to hmac 71 + * @niov: the length of @iov 72 + * @result: pointer to hold output hmac 73 + * @resultlen: pointer to hold length of @result 74 + * @errp: pointer to a NULL-initialized error object 75 + * 76 + * Computes the hmac across all the memory regions 77 + * present in @iov. The @result pointer will be 78 + * filled with raw bytes representing the computed 79 + * hmac, which will have length @resultlen. The 80 + * memory pointer in @result must be released 81 + * with a call to g_free() when no longer required. 82 + * 83 + * Returns: 84 + * 0 on success, -1 on error 85 + */ 86 + int qcrypto_hmac_bytesv(QCryptoHmac *hmac, 87 + const struct iovec *iov, 88 + size_t niov, 89 + uint8_t **result, 90 + size_t *resultlen, 91 + Error **errp); 92 + 93 + /** 94 + * qcrypto_hmac_bytes: 95 + * @hmac: the hmac object 96 + * @buf: the memory region to hmac 97 + * @len: the length of @buf 98 + * @result: pointer to hold output hmac 99 + * @resultlen: pointer to hold length of @result 100 + * @errp: pointer to a NULL-initialized error object 101 + * 102 + * Computes the hmac across all the memory region 103 + * @buf of length @len. The @result pointer will be 104 + * filled with raw bytes representing the computed 105 + * hmac, which will have length @resultlen. The 106 + * memory pointer in @result must be released 107 + * with a call to g_free() when no longer required. 108 + * 109 + * Returns: 110 + * 0 on success, -1 on error 111 + */ 112 + int qcrypto_hmac_bytes(QCryptoHmac *hmac, 113 + const char *buf, 114 + size_t len, 115 + uint8_t **result, 116 + size_t *resultlen, 117 + Error **errp); 118 + 119 + /** 120 + * qcrypto_hmac_digestv: 121 + * @hmac: the hmac object 122 + * @iov: the array of memory regions to hmac 123 + * @niov: the length of @iov 124 + * @digest: pointer to hold output hmac 125 + * @errp: pointer to a NULL-initialized error object 126 + * 127 + * Computes the hmac across all the memory regions 128 + * present in @iov. The @digest pointer will be 129 + * filled with the printable hex digest of the computed 130 + * hmac, which will be terminated by '\0'. The 131 + * memory pointer in @digest must be released 132 + * with a call to g_free() when no longer required. 133 + * 134 + * Returns: 135 + * 0 on success, -1 on error 136 + */ 137 + int qcrypto_hmac_digestv(QCryptoHmac *hmac, 138 + const struct iovec *iov, 139 + size_t niov, 140 + char **digest, 141 + Error **errp); 142 + 143 + /** 144 + * qcrypto_hmac_digest: 145 + * @hmac: the hmac object 146 + * @buf: the memory region to hmac 147 + * @len: the length of @buf 148 + * @digest: pointer to hold output hmac 149 + * @errp: pointer to a NULL-initialized error object 150 + * 151 + * Computes the hmac across all the memory region 152 + * @buf of length @len. The @digest pointer will be 153 + * filled with the printable hex digest of the computed 154 + * hmac, which will be terminated by '\0'. The 155 + * memory pointer in @digest must be released 156 + * with a call to g_free() when no longer required. 157 + * 158 + * Returns: 0 on success, -1 on error 159 + */ 160 + int qcrypto_hmac_digest(QCryptoHmac *hmac, 161 + const char *buf, 162 + size_t len, 163 + char **digest, 164 + Error **errp); 165 + 166 + #endif
+2 -1
qapi/crypto.json
··· 63 63 # @aes-192: AES with 192 bit / 24 byte keys 64 64 # @aes-256: AES with 256 bit / 32 byte keys 65 65 # @des-rfb: RFB specific variant of single DES. Do not use except in VNC. 66 + # @3des: 3DES(EDE) with 192 bit / 24 byte keys (since 2.9) 66 67 # @cast5-128: Cast5 with 128 bit / 16 byte keys 67 68 # @serpent-128: Serpent with 128 bit / 16 byte keys 68 69 # @serpent-192: Serpent with 192 bit / 24 byte keys ··· 75 76 { 'enum': 'QCryptoCipherAlgorithm', 76 77 'prefix': 'QCRYPTO_CIPHER_ALG', 77 78 'data': ['aes-128', 'aes-192', 'aes-256', 78 - 'des-rfb', 79 + 'des-rfb', '3des', 79 80 'cast5-128', 80 81 'serpent-128', 'serpent-192', 'serpent-256', 81 82 'twofish-128', 'twofish-192', 'twofish-256']}
+2
tests/Makefile.include
··· 91 91 check-unit-y += tests/test-write-threshold$(EXESUF) 92 92 gcov-files-test-write-threshold-y = block/write-threshold.c 93 93 check-unit-y += tests/test-crypto-hash$(EXESUF) 94 + check-unit-y += tests/test-crypto-hmac$(EXESUF) 94 95 check-unit-y += tests/test-crypto-cipher$(EXESUF) 95 96 check-unit-y += tests/test-crypto-secret$(EXESUF) 96 97 check-unit-$(CONFIG_GNUTLS) += tests/test-crypto-tlscredsx509$(EXESUF) ··· 571 572 tests/test-mul64$(EXESUF): tests/test-mul64.o $(test-util-obj-y) 572 573 tests/test-bitops$(EXESUF): tests/test-bitops.o $(test-util-obj-y) 573 574 tests/test-crypto-hash$(EXESUF): tests/test-crypto-hash.o $(test-crypto-obj-y) 575 + tests/test-crypto-hmac$(EXESUF): tests/test-crypto-hmac.o $(test-crypto-obj-y) 574 576 tests/test-crypto-cipher$(EXESUF): tests/test-crypto-cipher.o $(test-crypto-obj-y) 575 577 tests/test-crypto-secret$(EXESUF): tests/test-crypto-secret.o $(test-crypto-obj-y) 576 578 tests/test-crypto-xts$(EXESUF): tests/test-crypto-xts.o $(test-crypto-obj-y)
+119
tests/test-crypto-cipher.c
··· 165 165 "ffd29f1bb5596ad94ea2d8e6196b7f09" 166 166 "30d8ed0bf2773af36dd82a6280c20926", 167 167 }, 168 + #if defined(CONFIG_NETTLE) || defined(CONFIG_GCRYPT) 169 + { 170 + /* Borrowed from linux-kernel crypto/testmgr.h */ 171 + .path = "/crypto/cipher/3des-cbc", 172 + .alg = QCRYPTO_CIPHER_ALG_3DES, 173 + .mode = QCRYPTO_CIPHER_MODE_CBC, 174 + .key = 175 + "e9c0ff2e760b6424444d995a12d640c0" 176 + "eac284e81495dbe8", 177 + .iv = 178 + "7d3388930f93b242", 179 + .plaintext = 180 + "6f54206f614d796e5320636565727374" 181 + "54206f6f4d206e612079655372637465" 182 + "20736f54206f614d796e532063656572" 183 + "737454206f6f4d206e61207965537263" 184 + "746520736f54206f614d796e53206365" 185 + "6572737454206f6f4d206e6120796553" 186 + "7263746520736f54206f614d796e5320" 187 + "63656572737454206f6f4d206e610a79", 188 + .ciphertext = 189 + "0e2db6973c5633f4671721c76e8ad549" 190 + "74b34905c51cd0ed12565c5396b6007d" 191 + "9048fcf58d2939cc8ad5351836234ed7" 192 + "76d1da0c9467bb048bf2036ca8cfb6ea" 193 + "226447aa8f7513bf9fc2c3f0c956c57a" 194 + "71632e897b1e12cae25fafd8a4f8c97a" 195 + "d6f92131624445a6d6bc5ad32d5443cc" 196 + "9ddea570e942458a6bfab19113b0d919", 197 + }, 198 + { 199 + /* Borrowed from linux-kernel crypto/testmgr.h */ 200 + .path = "/crypto/cipher/3des-ecb", 201 + .alg = QCRYPTO_CIPHER_ALG_3DES, 202 + .mode = QCRYPTO_CIPHER_MODE_ECB, 203 + .key = 204 + "0123456789abcdef5555555555555555" 205 + "fedcba9876543210", 206 + .plaintext = 207 + "736f6d6564617461", 208 + .ciphertext = 209 + "18d748e563620572", 210 + }, 211 + { 212 + /* Borrowed from linux-kernel crypto/testmgr.h */ 213 + .path = "/crypto/cipher/3des-ctr", 214 + .alg = QCRYPTO_CIPHER_ALG_3DES, 215 + .mode = QCRYPTO_CIPHER_MODE_CTR, 216 + .key = 217 + "9cd6f39cb95a67005a67002dceeb2dce" 218 + "ebb45172b451721f", 219 + .iv = 220 + "ffffffffffffffff", 221 + .plaintext = 222 + "05ec77fb42d559208b128669f05bcf56" 223 + "39ad349f66ea7dc448d3ba0db118e34a" 224 + "fe41285c278e11856cf75ec2553ca00b" 225 + "9265e970db4fd6b900b41fe649fd442f" 226 + "533a8d149863ca5dc1a833a70e9178ec" 227 + "77de42d5bc078b12e54cf05b22563980" 228 + "6b9f66c950c4af36ba0d947fe34add41" 229 + "28b31a8e11f843f75e21553c876e9265" 230 + "cc57dba235b900eb72e649d0442fb619" 231 + "8d14ff46ca5d24a8339a6d9178c377de" 232 + "a108bc07ee71e54cd75b22b51c806bf2" 233 + "45c9503baf369960947fc64adda40fb3" 234 + "1aed74f8432a5e218813876ef158cc57" 235 + "3ea2359c67eb72c549d0bb02b619e04b" 236 + "ff46295d248f169a6df45fc3aa3da108" 237 + "937aee71d84cd7be01b51ce74ef2452c" 238 + "503b82159960cb52c6a930a40f9679ed" 239 + "74df432abd048813fa4df15823573e81" 240 + "689c67ce51c5ac37bb02957ce04bd246" 241 + "29b01b8f16f940f45f26aa3d846f937a" 242 + "cd54d8a30abe01e873e74ed1452cb71e" 243 + "8215fc47cb5225a9309b629679c074df" 244 + "a609bd04ef76fa4dd458238a1d8168f3" 245 + "5ace5138ac379e61957cc74bd2a50cb0" 246 + "1be275f9402b5f268910846ff659cd54" 247 + "3fa30a9d64e873da4ed1b803b71ee148" 248 + "fc472e52258c179b62f55cc0ab32a609" 249 + "907bef76d94dd4bf068a1de44ff35a2d" 250 + "5138836a9e61c853c7ae31a50c977ee2" 251 + "75dc402bb2058910fb42f65920543f86" 252 + "699d64cf56daad34b803ea7de148d347", 253 + .ciphertext = 254 + "07c20820721f49ef19cd6f3253052215" 255 + "a2852bdb85d2d8b9dd0d1b45cb6911d4" 256 + "eabeb2455d0caebea0c127ac659f537e" 257 + "afc21bb5b86d360c25c0f86d0b2901da" 258 + "1378dc89121243faf612ef8d87627883" 259 + "e2be41204c6d351bd10c30cfe2de2b03" 260 + "bf4573d4e55995d1b39b276297bdde7f" 261 + "a4d23980aa5023f074883da86a18793b" 262 + "c4966c8d2240926ed6ad2a1fde63c0e7" 263 + "07f72df7b5f3f0cc017c2a9bc210caaa" 264 + "fd2b3fc5f3f6fc9b45db53e45bf3c97b" 265 + "8e52ffc802b8ac9da10039da3d2d0e01" 266 + "097d8d5ebe53b9b08ee7e2966ab278ea" 267 + "de238ba5fa5ce3dabf8e316a55d16ab2" 268 + "b5466fa5f0eeba1f9f98b0664fd03fa9" 269 + "df5f58c4f4ff755c403a097e6e1c97d4" 270 + "cce7e771cf0b150871fa0797cde6ca1d" 271 + "14280ccf99137af1ebfafa9207de1da1" 272 + "d33669fe514d9f2e83374f1f4830ed04" 273 + "4da4ef3aca76f41c418f6337782f86a6" 274 + "ef417ed2af88ab675271c38ef8269372" 275 + "aad60ee70b46b13ab408a9a8a0cf200c" 276 + "52bc8b0556b2bc319b74b92929969a50" 277 + "dc45dc1aeb0c64d4d3057e5955c3f490" 278 + "c2abf89b8adacea1c3f4ad77dd44c8ac" 279 + "a3f1c9d2195cb0caa234c1f76cfdac65" 280 + "32dc48c4f2006b77f17d76acc031632a" 281 + "a53a62c891b10365cb43d106dfc367bc" 282 + "dce0cd35ce4965a0527ba70d07a91bb0" 283 + "407772c2ea0e3a7846b991b6e73d5142" 284 + "fd51b0c62c6313785ceefccfc4700034", 285 + }, 286 + #endif 168 287 { 169 288 /* RFC 2144, Appendix B.1 */ 170 289 .path = "/crypto/cipher/cast5-128",
+266
tests/test-crypto-hmac.c
··· 1 + /* 2 + * QEMU Crypto hmac algorithms tests 3 + * 4 + * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD. 5 + * 6 + * Authors: 7 + * Longpeng(Mike) <longpeng2@huawei.com> 8 + * 9 + * This work is licensed under the terms of the GNU GPL, version 2 or 10 + * (at your option) any later version. See the COPYING file in the 11 + * top-level directory. 12 + * 13 + */ 14 + 15 + #include "qemu/osdep.h" 16 + #include "crypto/init.h" 17 + #include "crypto/hmac.h" 18 + 19 + #define INPUT_TEXT1 "ABCDEFGHIJKLMNOPQRSTUVWXY" 20 + #define INPUT_TEXT2 "Zabcdefghijklmnopqrstuvwx" 21 + #define INPUT_TEXT3 "yz0123456789" 22 + #define INPUT_TEXT INPUT_TEXT1 \ 23 + INPUT_TEXT2 \ 24 + INPUT_TEXT3 25 + 26 + #define KEY "monkey monkey monkey monkey" 27 + 28 + typedef struct QCryptoHmacTestData QCryptoHmacTestData; 29 + struct QCryptoHmacTestData { 30 + QCryptoHashAlgorithm alg; 31 + const char *hex_digest; 32 + }; 33 + 34 + static QCryptoHmacTestData test_data[] = { 35 + { 36 + .alg = QCRYPTO_HASH_ALG_MD5, 37 + .hex_digest = 38 + "ede9cb83679ba82d88fbeae865b3f8fc", 39 + }, 40 + { 41 + .alg = QCRYPTO_HASH_ALG_SHA1, 42 + .hex_digest = 43 + "c7b5a631e3aac975c4ededfcd346e469" 44 + "dbc5f2d1", 45 + }, 46 + { 47 + .alg = QCRYPTO_HASH_ALG_SHA224, 48 + .hex_digest = 49 + "5f768179dbb29ca722875d0f461a2e2f" 50 + "597d0210340a84df1a8e9c63", 51 + }, 52 + { 53 + .alg = QCRYPTO_HASH_ALG_SHA256, 54 + .hex_digest = 55 + "3798f363c57afa6edaffe39016ca7bad" 56 + "efd1e670afb0e3987194307dec3197db", 57 + }, 58 + { 59 + .alg = QCRYPTO_HASH_ALG_SHA384, 60 + .hex_digest = 61 + "d218680a6032d33dccd9882d6a6a7164" 62 + "64f26623be257a9b2919b185294f4a49" 63 + "9e54b190bfd6bc5cedd2cd05c7e65e82", 64 + }, 65 + { 66 + .alg = QCRYPTO_HASH_ALG_SHA512, 67 + .hex_digest = 68 + "835a4f5b3750b4c1fccfa88da2f746a4" 69 + "900160c9f18964309bb736c13b59491b" 70 + "8e32d37b724cc5aebb0f554c6338a3b5" 71 + "94c4ba26862b2dadb59b7ede1d08d53e", 72 + }, 73 + { 74 + .alg = QCRYPTO_HASH_ALG_RIPEMD160, 75 + .hex_digest = 76 + "94964ed4c1155b62b668c241d67279e5" 77 + "8a711676", 78 + }, 79 + }; 80 + 81 + static const char hex[] = "0123456789abcdef"; 82 + 83 + static void test_hmac_alloc(void) 84 + { 85 + size_t i; 86 + 87 + for (i = 0; i < G_N_ELEMENTS(test_data); i++) { 88 + QCryptoHmacTestData *data = &test_data[i]; 89 + QCryptoHmac *hmac = NULL; 90 + uint8_t *result = NULL; 91 + size_t resultlen = 0; 92 + Error *err = NULL; 93 + const char *exp_output = NULL; 94 + int ret; 95 + size_t j; 96 + 97 + if (!qcrypto_hmac_supports(data->alg)) { 98 + return; 99 + } 100 + 101 + exp_output = data->hex_digest; 102 + 103 + hmac = qcrypto_hmac_new(data->alg, (const uint8_t *)KEY, 104 + strlen(KEY), &err); 105 + g_assert(err == NULL); 106 + g_assert(hmac != NULL); 107 + 108 + ret = qcrypto_hmac_bytes(hmac, (const char *)INPUT_TEXT, 109 + strlen(INPUT_TEXT), &result, 110 + &resultlen, &err); 111 + g_assert(err == NULL); 112 + g_assert(ret == 0); 113 + 114 + for (j = 0; j < resultlen; j++) { 115 + g_assert(exp_output[j * 2] == hex[(result[j] >> 4) & 0xf]); 116 + g_assert(exp_output[j * 2 + 1] == hex[result[j] & 0xf]); 117 + } 118 + 119 + qcrypto_hmac_free(hmac); 120 + 121 + g_free(result); 122 + } 123 + } 124 + 125 + static void test_hmac_prealloc(void) 126 + { 127 + size_t i; 128 + 129 + for (i = 0; i < G_N_ELEMENTS(test_data); i++) { 130 + QCryptoHmacTestData *data = &test_data[i]; 131 + QCryptoHmac *hmac = NULL; 132 + uint8_t *result = NULL; 133 + size_t resultlen = 0; 134 + Error *err = NULL; 135 + const char *exp_output = NULL; 136 + int ret; 137 + size_t j; 138 + 139 + if (!qcrypto_hmac_supports(data->alg)) { 140 + return; 141 + } 142 + 143 + exp_output = data->hex_digest; 144 + 145 + resultlen = strlen(exp_output) / 2; 146 + result = g_new0(uint8_t, resultlen); 147 + 148 + hmac = qcrypto_hmac_new(data->alg, (const uint8_t *)KEY, 149 + strlen(KEY), &err); 150 + g_assert(err == NULL); 151 + g_assert(hmac != NULL); 152 + 153 + ret = qcrypto_hmac_bytes(hmac, (const char *)INPUT_TEXT, 154 + strlen(INPUT_TEXT), &result, 155 + &resultlen, &err); 156 + g_assert(err == NULL); 157 + g_assert(ret == 0); 158 + 159 + exp_output = data->hex_digest; 160 + for (j = 0; j < resultlen; j++) { 161 + g_assert(exp_output[j * 2] == hex[(result[j] >> 4) & 0xf]); 162 + g_assert(exp_output[j * 2 + 1] == hex[result[j] & 0xf]); 163 + } 164 + 165 + qcrypto_hmac_free(hmac); 166 + 167 + g_free(result); 168 + } 169 + } 170 + 171 + static void test_hmac_iov(void) 172 + { 173 + size_t i; 174 + 175 + for (i = 0; i < G_N_ELEMENTS(test_data); i++) { 176 + QCryptoHmacTestData *data = &test_data[i]; 177 + QCryptoHmac *hmac = NULL; 178 + uint8_t *result = NULL; 179 + size_t resultlen = 0; 180 + Error *err = NULL; 181 + const char *exp_output = NULL; 182 + int ret; 183 + size_t j; 184 + struct iovec iov[3] = { 185 + { .iov_base = (char *)INPUT_TEXT1, .iov_len = strlen(INPUT_TEXT1) }, 186 + { .iov_base = (char *)INPUT_TEXT2, .iov_len = strlen(INPUT_TEXT2) }, 187 + { .iov_base = (char *)INPUT_TEXT3, .iov_len = strlen(INPUT_TEXT3) }, 188 + }; 189 + 190 + if (!qcrypto_hmac_supports(data->alg)) { 191 + return; 192 + } 193 + 194 + exp_output = data->hex_digest; 195 + 196 + hmac = qcrypto_hmac_new(data->alg, (const uint8_t *)KEY, 197 + strlen(KEY), &err); 198 + g_assert(err == NULL); 199 + g_assert(hmac != NULL); 200 + 201 + ret = qcrypto_hmac_bytesv(hmac, iov, 3, &result, 202 + &resultlen, &err); 203 + g_assert(err == NULL); 204 + g_assert(ret == 0); 205 + 206 + for (j = 0; j < resultlen; j++) { 207 + g_assert(exp_output[j * 2] == hex[(result[j] >> 4) & 0xf]); 208 + g_assert(exp_output[j * 2 + 1] == hex[result[j] & 0xf]); 209 + } 210 + 211 + qcrypto_hmac_free(hmac); 212 + 213 + g_free(result); 214 + } 215 + } 216 + 217 + static void test_hmac_digest(void) 218 + { 219 + size_t i; 220 + 221 + for (i = 0; i < G_N_ELEMENTS(test_data); i++) { 222 + QCryptoHmacTestData *data = &test_data[i]; 223 + QCryptoHmac *hmac = NULL; 224 + uint8_t *result = NULL; 225 + Error *err = NULL; 226 + const char *exp_output = NULL; 227 + int ret; 228 + 229 + if (!qcrypto_hmac_supports(data->alg)) { 230 + return; 231 + } 232 + 233 + exp_output = data->hex_digest; 234 + 235 + hmac = qcrypto_hmac_new(data->alg, (const uint8_t *)KEY, 236 + strlen(KEY), &err); 237 + g_assert(err == NULL); 238 + g_assert(hmac != NULL); 239 + 240 + ret = qcrypto_hmac_digest(hmac, (const char *)INPUT_TEXT, 241 + strlen(INPUT_TEXT), (char **)&result, 242 + &err); 243 + g_assert(err == NULL); 244 + g_assert(ret == 0); 245 + 246 + g_assert_cmpstr((const char *)result, ==, exp_output); 247 + 248 + qcrypto_hmac_free(hmac); 249 + 250 + g_free(result); 251 + } 252 + } 253 + 254 + int main(int argc, char **argv) 255 + { 256 + g_test_init(&argc, &argv, NULL); 257 + 258 + g_assert(qcrypto_init(NULL) == 0); 259 + 260 + g_test_add_func("/crypto/hmac/iov", test_hmac_iov); 261 + g_test_add_func("/crypto/hmac/alloc", test_hmac_alloc); 262 + g_test_add_func("/crypto/hmac/prealloc", test_hmac_prealloc); 263 + g_test_add_func("/crypto/hmac/digest", test_hmac_digest); 264 + 265 + return g_test_run(); 266 + }