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