1 /* 2 * QEMU crypto TLS credential support 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 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/tlscredspriv.h" 23 #include "trace.h" 24 25 #define DH_BITS 2048 26 27 #ifdef CONFIG_GNUTLS 28 int 29 qcrypto_tls_creds_get_dh_params_file(QCryptoTLSCreds *creds, 30 const char *filename, 31 gnutls_dh_params_t *dh_params, 32 Error **errp) 33 { 34 int ret; 35 36 trace_qcrypto_tls_creds_load_dh(creds, filename ? filename : "<generated>"); 37 38 if (filename == NULL) { 39 ret = gnutls_dh_params_init(dh_params); 40 if (ret < 0) { 41 error_setg(errp, "Unable to initialize DH parameters: %s", 42 gnutls_strerror(ret)); 43 return -1; 44 } 45 ret = gnutls_dh_params_generate2(*dh_params, DH_BITS); 46 if (ret < 0) { 47 gnutls_dh_params_deinit(*dh_params); 48 *dh_params = NULL; 49 error_setg(errp, "Unable to generate DH parameters: %s", 50 gnutls_strerror(ret)); 51 return -1; 52 } 53 } else { 54 GError *gerr = NULL; 55 gchar *contents; 56 gsize len; 57 gnutls_datum_t data; 58 if (!g_file_get_contents(filename, 59 &contents, 60 &len, 61 &gerr)) { 62 63 error_setg(errp, "%s", gerr->message); 64 g_error_free(gerr); 65 return -1; 66 } 67 data.data = (unsigned char *)contents; 68 data.size = len; 69 ret = gnutls_dh_params_init(dh_params); 70 if (ret < 0) { 71 g_free(contents); 72 error_setg(errp, "Unable to initialize DH parameters: %s", 73 gnutls_strerror(ret)); 74 return -1; 75 } 76 ret = gnutls_dh_params_import_pkcs3(*dh_params, 77 &data, 78 GNUTLS_X509_FMT_PEM); 79 g_free(contents); 80 if (ret < 0) { 81 gnutls_dh_params_deinit(*dh_params); 82 *dh_params = NULL; 83 error_setg(errp, "Unable to load DH parameters from %s: %s", 84 filename, gnutls_strerror(ret)); 85 return -1; 86 } 87 } 88 89 return 0; 90 } 91 92 93 int 94 qcrypto_tls_creds_get_path(QCryptoTLSCreds *creds, 95 const char *filename, 96 bool required, 97 char **cred, 98 Error **errp) 99 { 100 struct stat sb; 101 int ret = -1; 102 103 if (!creds->dir) { 104 if (required) { 105 error_setg(errp, "Missing 'dir' property value"); 106 return -1; 107 } else { 108 return 0; 109 } 110 } 111 112 *cred = g_strdup_printf("%s/%s", creds->dir, filename); 113 114 if (stat(*cred, &sb) < 0) { 115 if (errno == ENOENT && !required) { 116 ret = 0; 117 } else { 118 error_setg_errno(errp, errno, 119 "Unable to access credentials %s", 120 *cred); 121 } 122 g_free(*cred); 123 *cred = NULL; 124 goto cleanup; 125 } 126 127 ret = 0; 128 cleanup: 129 trace_qcrypto_tls_creds_get_path(creds, filename, 130 *cred ? *cred : "<none>"); 131 return ret; 132 } 133 134 135 #endif /* ! CONFIG_GNUTLS */ 136 137 138 static void 139 qcrypto_tls_creds_prop_set_verify(Object *obj, 140 bool value, 141 Error **errp G_GNUC_UNUSED) 142 { 143 QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj); 144 145 creds->verifyPeer = value; 146 } 147 148 149 static bool 150 qcrypto_tls_creds_prop_get_verify(Object *obj, 151 Error **errp G_GNUC_UNUSED) 152 { 153 QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj); 154 155 return creds->verifyPeer; 156 } 157 158 159 static void 160 qcrypto_tls_creds_prop_set_dir(Object *obj, 161 const char *value, 162 Error **errp G_GNUC_UNUSED) 163 { 164 QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj); 165 166 creds->dir = g_strdup(value); 167 } 168 169 170 static char * 171 qcrypto_tls_creds_prop_get_dir(Object *obj, 172 Error **errp G_GNUC_UNUSED) 173 { 174 QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj); 175 176 return g_strdup(creds->dir); 177 } 178 179 180 static void 181 qcrypto_tls_creds_prop_set_endpoint(Object *obj, 182 int value, 183 Error **errp G_GNUC_UNUSED) 184 { 185 QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj); 186 187 creds->endpoint = value; 188 } 189 190 191 static int 192 qcrypto_tls_creds_prop_get_endpoint(Object *obj, 193 Error **errp G_GNUC_UNUSED) 194 { 195 QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj); 196 197 return creds->endpoint; 198 } 199 200 201 static void 202 qcrypto_tls_creds_class_init(ObjectClass *oc, void *data) 203 { 204 object_class_property_add_bool(oc, "verify-peer", 205 qcrypto_tls_creds_prop_get_verify, 206 qcrypto_tls_creds_prop_set_verify, 207 NULL); 208 object_class_property_add_str(oc, "dir", 209 qcrypto_tls_creds_prop_get_dir, 210 qcrypto_tls_creds_prop_set_dir, 211 NULL); 212 object_class_property_add_enum(oc, "endpoint", 213 "QCryptoTLSCredsEndpoint", 214 QCryptoTLSCredsEndpoint_lookup, 215 qcrypto_tls_creds_prop_get_endpoint, 216 qcrypto_tls_creds_prop_set_endpoint, 217 NULL); 218 } 219 220 221 static void 222 qcrypto_tls_creds_init(Object *obj) 223 { 224 QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj); 225 226 creds->verifyPeer = true; 227 } 228 229 230 static void 231 qcrypto_tls_creds_finalize(Object *obj) 232 { 233 QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj); 234 235 g_free(creds->dir); 236 } 237 238 239 static const TypeInfo qcrypto_tls_creds_info = { 240 .parent = TYPE_OBJECT, 241 .name = TYPE_QCRYPTO_TLS_CREDS, 242 .instance_size = sizeof(QCryptoTLSCreds), 243 .instance_init = qcrypto_tls_creds_init, 244 .instance_finalize = qcrypto_tls_creds_finalize, 245 .class_init = qcrypto_tls_creds_class_init, 246 .class_size = sizeof(QCryptoTLSCredsClass), 247 .abstract = true, 248 }; 249 250 251 static void 252 qcrypto_tls_creds_register_types(void) 253 { 254 type_register_static(&qcrypto_tls_creds_info); 255 } 256 257 258 type_init(qcrypto_tls_creds_register_types); 259