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 #include "hmacpriv.h" 16 17 static const char hex[] = "0123456789abcdef"; 18 19 int qcrypto_hmac_bytesv(QCryptoHmac *hmac, 20 const struct iovec *iov, 21 size_t niov, 22 uint8_t **result, 23 size_t *resultlen, 24 Error **errp) 25 { 26 QCryptoHmacDriver *drv = hmac->driver; 27 28 return drv->hmac_bytesv(hmac, iov, niov, result, resultlen, errp); 29 } 30 31 int qcrypto_hmac_bytes(QCryptoHmac *hmac, 32 const char *buf, 33 size_t len, 34 uint8_t **result, 35 size_t *resultlen, 36 Error **errp) 37 { 38 struct iovec iov = { 39 .iov_base = (char *)buf, 40 .iov_len = len 41 }; 42 43 return qcrypto_hmac_bytesv(hmac, &iov, 1, result, resultlen, errp); 44 } 45 46 int qcrypto_hmac_digestv(QCryptoHmac *hmac, 47 const struct iovec *iov, 48 size_t niov, 49 char **digest, 50 Error **errp) 51 { 52 uint8_t *result = NULL; 53 size_t resultlen = 0; 54 size_t i; 55 56 if (qcrypto_hmac_bytesv(hmac, iov, niov, &result, &resultlen, errp) < 0) { 57 return -1; 58 } 59 60 *digest = g_new0(char, (resultlen * 2) + 1); 61 62 for (i = 0 ; i < resultlen ; i++) { 63 (*digest)[(i * 2)] = hex[(result[i] >> 4) & 0xf]; 64 (*digest)[(i * 2) + 1] = hex[result[i] & 0xf]; 65 } 66 67 (*digest)[resultlen * 2] = '\0'; 68 69 g_free(result); 70 return 0; 71 } 72 73 int qcrypto_hmac_digest(QCryptoHmac *hmac, 74 const char *buf, 75 size_t len, 76 char **digest, 77 Error **errp) 78 { 79 struct iovec iov = { 80 .iov_base = (char *)buf, 81 .iov_len = len 82 }; 83 84 return qcrypto_hmac_digestv(hmac, &iov, 1, digest, errp); 85 } 86 87 QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg, 88 const uint8_t *key, size_t nkey, 89 Error **errp) 90 { 91 QCryptoHmac *hmac; 92 void *ctx = NULL; 93 QCryptoHmacDriver *drv = NULL; 94 95 #ifdef CONFIG_AF_ALG 96 ctx = qcrypto_afalg_hmac_ctx_new(alg, key, nkey, NULL); 97 if (ctx) { 98 drv = &qcrypto_hmac_afalg_driver; 99 } 100 #endif 101 102 if (!ctx) { 103 ctx = qcrypto_hmac_ctx_new(alg, key, nkey, errp); 104 if (!ctx) { 105 return NULL; 106 } 107 108 drv = &qcrypto_hmac_lib_driver; 109 } 110 111 hmac = g_new0(QCryptoHmac, 1); 112 hmac->alg = alg; 113 hmac->opaque = ctx; 114 hmac->driver = (void *)drv; 115 116 return hmac; 117 } 118 119 void qcrypto_hmac_free(QCryptoHmac *hmac) 120 { 121 QCryptoHmacDriver *drv; 122 123 if (hmac) { 124 drv = hmac->driver; 125 drv->hmac_free(hmac); 126 g_free(hmac); 127 } 128 } 129