Skip to content

Commit

Permalink
crypto: Introduce x509 utils
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
dorjoy03 authored and berrange committed Sep 9, 2024
1 parent 9893da7 commit 10a1d34
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 0 deletions.
4 changes: 4 additions & 0 deletions crypto/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ crypto_ss.add(files(
'rsakey.c',
))

if gnutls.found()
crypto_ss.add(files('x509-utils.c'))
endif

if nettle.found()
crypto_ss.add(nettle, files('hash-nettle.c', 'hmac-nettle.c', 'pbkdf-nettle.c'))
if hogweed.found()
Expand Down
76 changes: 76 additions & 0 deletions crypto/x509-utils.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* X.509 certificate related helpers
*
* Copyright (c) 2024 Dorjoy Chowdhury <[email protected]>
*
* This work is licensed under the terms of the GNU GPL, version 2 or
* (at your option) any later version. See the COPYING file in the
* top-level directory.
*/

#include "qemu/osdep.h"
#include "qapi/error.h"
#include "crypto/x509-utils.h"
#include <gnutls/gnutls.h>
#include <gnutls/crypto.h>
#include <gnutls/x509.h>

static const int qcrypto_to_gnutls_hash_alg_map[QCRYPTO_HASH_ALG__MAX] = {
[QCRYPTO_HASH_ALG_MD5] = GNUTLS_DIG_MD5,
[QCRYPTO_HASH_ALG_SHA1] = GNUTLS_DIG_SHA1,
[QCRYPTO_HASH_ALG_SHA224] = GNUTLS_DIG_SHA224,
[QCRYPTO_HASH_ALG_SHA256] = GNUTLS_DIG_SHA256,
[QCRYPTO_HASH_ALG_SHA384] = GNUTLS_DIG_SHA384,
[QCRYPTO_HASH_ALG_SHA512] = GNUTLS_DIG_SHA512,
[QCRYPTO_HASH_ALG_RIPEMD160] = GNUTLS_DIG_RMD160,
};

int qcrypto_get_x509_cert_fingerprint(uint8_t *cert, size_t size,
QCryptoHashAlgorithm alg,
uint8_t *result,
size_t *resultlen,
Error **errp)
{
int ret = -1;
int hlen;
gnutls_x509_crt_t crt;
gnutls_datum_t datum = {.data = cert, .size = size};

if (alg >= G_N_ELEMENTS(qcrypto_to_gnutls_hash_alg_map)) {
error_setg(errp, "Unknown hash algorithm");
return -1;
}

if (result == NULL) {
error_setg(errp, "No valid buffer given");
return -1;
}

gnutls_x509_crt_init(&crt);

if (gnutls_x509_crt_import(crt, &datum, GNUTLS_X509_FMT_PEM) != 0) {
error_setg(errp, "Failed to import certificate");
goto cleanup;
}

hlen = gnutls_hash_get_len(qcrypto_to_gnutls_hash_alg_map[alg]);
if (*resultlen < hlen) {
error_setg(errp,
"Result buffer size %zu is smaller than hash %d",
*resultlen, hlen);
goto cleanup;
}

if (gnutls_x509_crt_get_fingerprint(crt,
qcrypto_to_gnutls_hash_alg_map[alg],
result, resultlen) != 0) {
error_setg(errp, "Failed to get fingerprint from certificate");
goto cleanup;
}

ret = 0;

cleanup:
gnutls_x509_crt_deinit(crt);
return ret;
}
22 changes: 22 additions & 0 deletions include/crypto/x509-utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* X.509 certificate related helpers
*
* Copyright (c) 2024 Dorjoy Chowdhury <[email protected]>
*
* This work is licensed under the terms of the GNU GPL, version 2 or
* (at your option) any later version. See the COPYING file in the
* top-level directory.
*/

#ifndef QCRYPTO_X509_UTILS_H
#define QCRYPTO_X509_UTILS_H

#include "crypto/hash.h"

int qcrypto_get_x509_cert_fingerprint(uint8_t *cert, size_t size,
QCryptoHashAlgorithm hash,
uint8_t *result,
size_t *resultlen,
Error **errp);

#endif

0 comments on commit 10a1d34

Please sign in to comment.