1 /*
2 * X.509 certificate related helpers
3 *
4 * Copyright (c) 2024 Dorjoy Chowdhury <dorjoychy111@gmail.com>
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 #include "qemu/osdep.h"
12 #include "qapi/error.h"
13 #include "crypto/x509-utils.h"
14 #include <gnutls/gnutls.h>
15 #include <gnutls/crypto.h>
16 #include <gnutls/x509.h>
17
18 static const int qcrypto_to_gnutls_hash_alg_map[QCRYPTO_HASH_ALGO__MAX] = {
19 [QCRYPTO_HASH_ALGO_MD5] = GNUTLS_DIG_MD5,
20 [QCRYPTO_HASH_ALGO_SHA1] = GNUTLS_DIG_SHA1,
21 [QCRYPTO_HASH_ALGO_SHA224] = GNUTLS_DIG_SHA224,
22 [QCRYPTO_HASH_ALGO_SHA256] = GNUTLS_DIG_SHA256,
23 [QCRYPTO_HASH_ALGO_SHA384] = GNUTLS_DIG_SHA384,
24 [QCRYPTO_HASH_ALGO_SHA512] = GNUTLS_DIG_SHA512,
25 [QCRYPTO_HASH_ALGO_RIPEMD160] = GNUTLS_DIG_RMD160,
26 };
27
qcrypto_get_x509_cert_fingerprint(uint8_t * cert,size_t size,QCryptoHashAlgo alg,uint8_t * result,size_t * resultlen,Error ** errp)28 int qcrypto_get_x509_cert_fingerprint(uint8_t *cert, size_t size,
29 QCryptoHashAlgo alg,
30 uint8_t *result,
31 size_t *resultlen,
32 Error **errp)
33 {
34 int ret = -1;
35 int hlen;
36 gnutls_x509_crt_t crt;
37 gnutls_datum_t datum = {.data = cert, .size = size};
38
39 if (alg >= G_N_ELEMENTS(qcrypto_to_gnutls_hash_alg_map)) {
40 error_setg(errp, "Unknown hash algorithm");
41 return -1;
42 }
43
44 if (result == NULL) {
45 error_setg(errp, "No valid buffer given");
46 return -1;
47 }
48
49 gnutls_x509_crt_init(&crt);
50
51 if (gnutls_x509_crt_import(crt, &datum, GNUTLS_X509_FMT_PEM) != 0) {
52 error_setg(errp, "Failed to import certificate");
53 goto cleanup;
54 }
55
56 hlen = gnutls_hash_get_len(qcrypto_to_gnutls_hash_alg_map[alg]);
57 if (*resultlen < hlen) {
58 error_setg(errp,
59 "Result buffer size %zu is smaller than hash %d",
60 *resultlen, hlen);
61 goto cleanup;
62 }
63
64 if (gnutls_x509_crt_get_fingerprint(crt,
65 qcrypto_to_gnutls_hash_alg_map[alg],
66 result, resultlen) != 0) {
67 error_setg(errp, "Failed to get fingerprint from certificate");
68 goto cleanup;
69 }
70
71 ret = 0;
72
73 cleanup:
74 gnutls_x509_crt_deinit(crt);
75 return ret;
76 }
77