master
c 101 lines 2.3 KB
Raw
1 /*
2 * SPDX-License-Identifier: GPL-2.0-or-later
3 *
4 * QEMU crypto TLS credential support
5 *
6 * Copyright (c) 2025 Red Hat, Inc.
7 */
8
9 #include "qemu/osdep.h"
10 #include "crypto/tlscredsbox.h"
11 #include "qemu/atomic.h"
12
13
14 static QCryptoTLSCredsBox *
15 qcrypto_tls_creds_box_new_impl(int type, bool server)
16 {
17 QCryptoTLSCredsBox *credsbox = g_new0(QCryptoTLSCredsBox, 1);
18 credsbox->ref = 1;
19 credsbox->server = server;
20 credsbox->type = type;
21 return credsbox;
22 }
23
24
25 QCryptoTLSCredsBox *
26 qcrypto_tls_creds_box_new_server(int type)
27 {
28 return qcrypto_tls_creds_box_new_impl(type, true);
29 }
30
31
32 QCryptoTLSCredsBox *
33 qcrypto_tls_creds_box_new_client(int type)
34 {
35 return qcrypto_tls_creds_box_new_impl(type, false);
36 }
37
38 static void qcrypto_tls_creds_box_free(QCryptoTLSCredsBox *credsbox)
39 {
40 switch (credsbox->type) {
41 case GNUTLS_CRD_CERTIFICATE:
42 if (credsbox->data.cert) {
43 gnutls_certificate_free_credentials(credsbox->data.cert);
44 }
45 break;
46 case GNUTLS_CRD_PSK:
47 if (credsbox->server) {
48 if (credsbox->data.pskserver) {
49 gnutls_psk_free_server_credentials(credsbox->data.pskserver);
50 }
51 } else {
52 if (credsbox->data.pskclient) {
53 gnutls_psk_free_client_credentials(credsbox->data.pskclient);
54 }
55 }
56 break;
57 case GNUTLS_CRD_ANON:
58 if (credsbox->server) {
59 if (credsbox->data.anonserver) {
60 gnutls_anon_free_server_credentials(credsbox->data.anonserver);
61 }
62 } else {
63 if (credsbox->data.anonclient) {
64 gnutls_anon_free_client_credentials(credsbox->data.anonclient);
65 }
66 }
67 break;
68 default:
69 g_assert_not_reached();
70 }
71
72 if (credsbox->dh_params) {
73 gnutls_dh_params_deinit(credsbox->dh_params);
74 }
75
76 g_free(credsbox);
77 }
78
79
80 void qcrypto_tls_creds_box_ref(QCryptoTLSCredsBox *credsbox)
81 {
82 uint32_t ref = qatomic_fetch_inc(&credsbox->ref);
83 /* Assert waaay before the integer overflows */
84 g_assert(ref < INT_MAX);
85 }
86
87
88 void qcrypto_tls_creds_box_unref(QCryptoTLSCredsBox *credsbox)
89 {
90 if (!credsbox) {
91 return;
92 }
93
94 g_assert(credsbox->ref > 0);
95
96 if (qatomic_fetch_dec(&credsbox->ref) == 1) {
97 qcrypto_tls_creds_box_free(credsbox);
98 }
99
100 }
101