Skip to content

Commit 10a1d34

Browse files
dorjoy03berrange
authored andcommitted
crypto: Introduce x509 utils
An utility function for getting fingerprint from X.509 certificate has been introduced. Implementation only provided using gnutls. Signed-off-by: Dorjoy Chowdhury <[email protected]> [DB: fixed missing gnutls_x509_crt_deinit in success path] Reviewed-by: Philippe Mathieu-Daudé <[email protected]> Signed-off-by: Daniel P. Berrangé <[email protected]>
1 parent 9893da7 commit 10a1d34

File tree

3 files changed

+102
-0
lines changed

3 files changed

+102
-0
lines changed

crypto/meson.build

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ crypto_ss.add(files(
2424
'rsakey.c',
2525
))
2626

27+
if gnutls.found()
28+
crypto_ss.add(files('x509-utils.c'))
29+
endif
30+
2731
if nettle.found()
2832
crypto_ss.add(nettle, files('hash-nettle.c', 'hmac-nettle.c', 'pbkdf-nettle.c'))
2933
if hogweed.found()

crypto/x509-utils.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* X.509 certificate related helpers
3+
*
4+
* Copyright (c) 2024 Dorjoy Chowdhury <[email protected]>
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_ALG__MAX] = {
19+
[QCRYPTO_HASH_ALG_MD5] = GNUTLS_DIG_MD5,
20+
[QCRYPTO_HASH_ALG_SHA1] = GNUTLS_DIG_SHA1,
21+
[QCRYPTO_HASH_ALG_SHA224] = GNUTLS_DIG_SHA224,
22+
[QCRYPTO_HASH_ALG_SHA256] = GNUTLS_DIG_SHA256,
23+
[QCRYPTO_HASH_ALG_SHA384] = GNUTLS_DIG_SHA384,
24+
[QCRYPTO_HASH_ALG_SHA512] = GNUTLS_DIG_SHA512,
25+
[QCRYPTO_HASH_ALG_RIPEMD160] = GNUTLS_DIG_RMD160,
26+
};
27+
28+
int qcrypto_get_x509_cert_fingerprint(uint8_t *cert, size_t size,
29+
QCryptoHashAlgorithm 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+
}

include/crypto/x509-utils.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* X.509 certificate related helpers
3+
*
4+
* Copyright (c) 2024 Dorjoy Chowdhury <[email protected]>
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+
#ifndef QCRYPTO_X509_UTILS_H
12+
#define QCRYPTO_X509_UTILS_H
13+
14+
#include "crypto/hash.h"
15+
16+
int qcrypto_get_x509_cert_fingerprint(uint8_t *cert, size_t size,
17+
QCryptoHashAlgorithm hash,
18+
uint8_t *result,
19+
size_t *resultlen,
20+
Error **errp);
21+
22+
#endif

0 commit comments

Comments
 (0)