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