xref: /openbmc/qemu/crypto/hash.c (revision d0f0cd5b)
1 /*
2  * QEMU Crypto hash algorithms
3  *
4  * Copyright (c) 2015 Red Hat, Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #include "qemu/osdep.h"
22 #include "crypto/hash.h"
23 #include "hashpriv.h"
24 
25 static size_t qcrypto_hash_alg_size[QCRYPTO_HASH_ALGO__MAX] = {
26     [QCRYPTO_HASH_ALGO_MD5]       = QCRYPTO_HASH_DIGEST_LEN_MD5,
27     [QCRYPTO_HASH_ALGO_SHA1]      = QCRYPTO_HASH_DIGEST_LEN_SHA1,
28     [QCRYPTO_HASH_ALGO_SHA224]    = QCRYPTO_HASH_DIGEST_LEN_SHA224,
29     [QCRYPTO_HASH_ALGO_SHA256]    = QCRYPTO_HASH_DIGEST_LEN_SHA256,
30     [QCRYPTO_HASH_ALGO_SHA384]    = QCRYPTO_HASH_DIGEST_LEN_SHA384,
31     [QCRYPTO_HASH_ALGO_SHA512]    = QCRYPTO_HASH_DIGEST_LEN_SHA512,
32     [QCRYPTO_HASH_ALGO_RIPEMD160] = QCRYPTO_HASH_DIGEST_LEN_RIPEMD160,
33 };
34 
35 size_t qcrypto_hash_digest_len(QCryptoHashAlgo alg)
36 {
37     assert(alg < G_N_ELEMENTS(qcrypto_hash_alg_size));
38     return qcrypto_hash_alg_size[alg];
39 }
40 
41 int qcrypto_hash_bytesv(QCryptoHashAlgo alg,
42                         const struct iovec *iov,
43                         size_t niov,
44                         uint8_t **result,
45                         size_t *resultlen,
46                         Error **errp)
47 {
48 #ifdef CONFIG_AF_ALG
49     int ret;
50     /*
51      * TODO:
52      * Maybe we should treat some afalg errors as fatal
53      */
54     ret = qcrypto_hash_afalg_driver.hash_bytesv(alg, iov, niov,
55                                                 result, resultlen,
56                                                 NULL);
57     if (ret == 0) {
58         return ret;
59     }
60 #endif
61 
62     return qcrypto_hash_lib_driver.hash_bytesv(alg, iov, niov,
63                                                result, resultlen,
64                                                errp);
65 }
66 
67 
68 int qcrypto_hash_bytes(QCryptoHashAlgo alg,
69                        const char *buf,
70                        size_t len,
71                        uint8_t **result,
72                        size_t *resultlen,
73                        Error **errp)
74 {
75     struct iovec iov = { .iov_base = (char *)buf,
76                          .iov_len = len };
77     return qcrypto_hash_bytesv(alg, &iov, 1, result, resultlen, errp);
78 }
79 
80 static const char hex[] = "0123456789abcdef";
81 
82 int qcrypto_hash_digestv(QCryptoHashAlgo alg,
83                          const struct iovec *iov,
84                          size_t niov,
85                          char **digest,
86                          Error **errp)
87 {
88     uint8_t *result = NULL;
89     size_t resultlen = 0;
90     size_t i;
91 
92     if (qcrypto_hash_bytesv(alg, iov, niov, &result, &resultlen, errp) < 0) {
93         return -1;
94     }
95 
96     *digest = g_new0(char, (resultlen * 2) + 1);
97     for (i = 0 ; i < resultlen ; i++) {
98         (*digest)[(i * 2)] = hex[(result[i] >> 4) & 0xf];
99         (*digest)[(i * 2) + 1] = hex[result[i] & 0xf];
100     }
101     (*digest)[resultlen * 2] = '\0';
102     g_free(result);
103     return 0;
104 }
105 
106 int qcrypto_hash_digest(QCryptoHashAlgo alg,
107                         const char *buf,
108                         size_t len,
109                         char **digest,
110                         Error **errp)
111 {
112     struct iovec iov = { .iov_base = (char *)buf, .iov_len = len };
113 
114     return qcrypto_hash_digestv(alg, &iov, 1, digest, errp);
115 }
116 
117 int qcrypto_hash_base64v(QCryptoHashAlgo alg,
118                          const struct iovec *iov,
119                          size_t niov,
120                          char **base64,
121                          Error **errp)
122 {
123     uint8_t *result = NULL;
124     size_t resultlen = 0;
125 
126     if (qcrypto_hash_bytesv(alg, iov, niov, &result, &resultlen, errp) < 0) {
127         return -1;
128     }
129 
130     *base64 = g_base64_encode(result, resultlen);
131     g_free(result);
132     return 0;
133 }
134 
135 int qcrypto_hash_base64(QCryptoHashAlgo alg,
136                         const char *buf,
137                         size_t len,
138                         char **base64,
139                         Error **errp)
140 {
141     struct iovec iov = { .iov_base = (char *)buf, .iov_len = len };
142 
143     return qcrypto_hash_base64v(alg, &iov, 1, base64, errp);
144 }
145