1 /* 2 * QEMU crypto secret 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.1 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/secret.h" 23 #include "crypto/cipher.h" 24 #include "qapi/error.h" 25 #include "qom/object_interfaces.h" 26 #include "qemu/base64.h" 27 #include "qemu/module.h" 28 #include "trace.h" 29 30 31 static void 32 qcrypto_secret_load_data(QCryptoSecret *secret, 33 uint8_t **output, 34 size_t *outputlen, 35 Error **errp) 36 { 37 char *data = NULL; 38 size_t length = 0; 39 GError *gerr = NULL; 40 41 *output = NULL; 42 *outputlen = 0; 43 44 if (secret->file) { 45 if (secret->data) { 46 error_setg(errp, 47 "'file' and 'data' are mutually exclusive"); 48 return; 49 } 50 if (!g_file_get_contents(secret->file, &data, &length, &gerr)) { 51 error_setg(errp, 52 "Unable to read %s: %s", 53 secret->file, gerr->message); 54 g_error_free(gerr); 55 return; 56 } 57 *output = (uint8_t *)data; 58 *outputlen = length; 59 } else if (secret->data) { 60 *outputlen = strlen(secret->data); 61 *output = (uint8_t *)g_strdup(secret->data); 62 } else { 63 error_setg(errp, "Either 'file' or 'data' must be provided"); 64 } 65 } 66 67 68 static void qcrypto_secret_decrypt(QCryptoSecret *secret, 69 const uint8_t *input, 70 size_t inputlen, 71 uint8_t **output, 72 size_t *outputlen, 73 Error **errp) 74 { 75 g_autofree uint8_t *key = NULL; 76 g_autofree uint8_t *ciphertext = NULL; 77 g_autofree uint8_t *iv = NULL; 78 size_t keylen, ciphertextlen, ivlen; 79 g_autoptr(QCryptoCipher) aes = NULL; 80 g_autofree uint8_t *plaintext = NULL; 81 82 *output = NULL; 83 *outputlen = 0; 84 85 if (qcrypto_secret_lookup(secret->keyid, 86 &key, &keylen, 87 errp) < 0) { 88 return; 89 } 90 91 if (keylen != 32) { 92 error_setg(errp, "Key should be 32 bytes in length"); 93 return; 94 } 95 96 if (!secret->iv) { 97 error_setg(errp, "IV is required to decrypt secret"); 98 return; 99 } 100 101 iv = qbase64_decode(secret->iv, -1, &ivlen, errp); 102 if (!iv) { 103 return; 104 } 105 if (ivlen != 16) { 106 error_setg(errp, "IV should be 16 bytes in length not %zu", 107 ivlen); 108 return; 109 } 110 111 aes = qcrypto_cipher_new(QCRYPTO_CIPHER_ALG_AES_256, 112 QCRYPTO_CIPHER_MODE_CBC, 113 key, keylen, 114 errp); 115 if (!aes) { 116 return; 117 } 118 119 if (qcrypto_cipher_setiv(aes, iv, ivlen, errp) < 0) { 120 return; 121 } 122 123 if (secret->format == QCRYPTO_SECRET_FORMAT_BASE64) { 124 ciphertext = qbase64_decode((const gchar*)input, 125 inputlen, 126 &ciphertextlen, 127 errp); 128 if (!ciphertext) { 129 return; 130 } 131 plaintext = g_new0(uint8_t, ciphertextlen + 1); 132 } else { 133 ciphertextlen = inputlen; 134 plaintext = g_new0(uint8_t, inputlen + 1); 135 } 136 if (qcrypto_cipher_decrypt(aes, 137 ciphertext ? ciphertext : input, 138 plaintext, 139 ciphertextlen, 140 errp) < 0) { 141 return; 142 } 143 144 if (plaintext[ciphertextlen - 1] > 16 || 145 plaintext[ciphertextlen - 1] > ciphertextlen) { 146 error_setg(errp, "Incorrect number of padding bytes (%d) " 147 "found on decrypted data", 148 (int)plaintext[ciphertextlen - 1]); 149 return; 150 } 151 152 /* Even though plaintext may contain arbitrary NUL 153 * ensure it is explicitly NUL terminated. 154 */ 155 ciphertextlen -= plaintext[ciphertextlen - 1]; 156 plaintext[ciphertextlen] = '\0'; 157 158 *output = g_steal_pointer(&plaintext); 159 *outputlen = ciphertextlen; 160 } 161 162 163 static void qcrypto_secret_decode(const uint8_t *input, 164 size_t inputlen, 165 uint8_t **output, 166 size_t *outputlen, 167 Error **errp) 168 { 169 *output = qbase64_decode((const gchar*)input, 170 inputlen, 171 outputlen, 172 errp); 173 } 174 175 176 static void 177 qcrypto_secret_prop_set_loaded(Object *obj, 178 bool value, 179 Error **errp) 180 { 181 QCryptoSecret *secret = QCRYPTO_SECRET(obj); 182 183 if (value) { 184 Error *local_err = NULL; 185 uint8_t *input = NULL; 186 size_t inputlen = 0; 187 uint8_t *output = NULL; 188 size_t outputlen = 0; 189 190 qcrypto_secret_load_data(secret, &input, &inputlen, &local_err); 191 if (local_err) { 192 error_propagate(errp, local_err); 193 return; 194 } 195 196 if (secret->keyid) { 197 qcrypto_secret_decrypt(secret, input, inputlen, 198 &output, &outputlen, &local_err); 199 g_free(input); 200 if (local_err) { 201 error_propagate(errp, local_err); 202 return; 203 } 204 input = output; 205 inputlen = outputlen; 206 } else { 207 if (secret->format == QCRYPTO_SECRET_FORMAT_BASE64) { 208 qcrypto_secret_decode(input, inputlen, 209 &output, &outputlen, &local_err); 210 g_free(input); 211 if (local_err) { 212 error_propagate(errp, local_err); 213 return; 214 } 215 input = output; 216 inputlen = outputlen; 217 } 218 } 219 220 secret->rawdata = input; 221 secret->rawlen = inputlen; 222 } else { 223 g_free(secret->rawdata); 224 secret->rawdata = NULL; 225 secret->rawlen = 0; 226 } 227 } 228 229 230 static bool 231 qcrypto_secret_prop_get_loaded(Object *obj, 232 Error **errp G_GNUC_UNUSED) 233 { 234 QCryptoSecret *secret = QCRYPTO_SECRET(obj); 235 return secret->rawdata != NULL; 236 } 237 238 239 static void 240 qcrypto_secret_prop_set_format(Object *obj, 241 int value, 242 Error **errp G_GNUC_UNUSED) 243 { 244 QCryptoSecret *creds = QCRYPTO_SECRET(obj); 245 246 creds->format = value; 247 } 248 249 250 static int 251 qcrypto_secret_prop_get_format(Object *obj, 252 Error **errp G_GNUC_UNUSED) 253 { 254 QCryptoSecret *creds = QCRYPTO_SECRET(obj); 255 256 return creds->format; 257 } 258 259 260 static void 261 qcrypto_secret_prop_set_data(Object *obj, 262 const char *value, 263 Error **errp) 264 { 265 QCryptoSecret *secret = QCRYPTO_SECRET(obj); 266 267 g_free(secret->data); 268 secret->data = g_strdup(value); 269 } 270 271 272 static char * 273 qcrypto_secret_prop_get_data(Object *obj, 274 Error **errp) 275 { 276 QCryptoSecret *secret = QCRYPTO_SECRET(obj); 277 return g_strdup(secret->data); 278 } 279 280 281 static void 282 qcrypto_secret_prop_set_file(Object *obj, 283 const char *value, 284 Error **errp) 285 { 286 QCryptoSecret *secret = QCRYPTO_SECRET(obj); 287 288 g_free(secret->file); 289 secret->file = g_strdup(value); 290 } 291 292 293 static char * 294 qcrypto_secret_prop_get_file(Object *obj, 295 Error **errp) 296 { 297 QCryptoSecret *secret = QCRYPTO_SECRET(obj); 298 return g_strdup(secret->file); 299 } 300 301 302 static void 303 qcrypto_secret_prop_set_iv(Object *obj, 304 const char *value, 305 Error **errp) 306 { 307 QCryptoSecret *secret = QCRYPTO_SECRET(obj); 308 309 g_free(secret->iv); 310 secret->iv = g_strdup(value); 311 } 312 313 314 static char * 315 qcrypto_secret_prop_get_iv(Object *obj, 316 Error **errp) 317 { 318 QCryptoSecret *secret = QCRYPTO_SECRET(obj); 319 return g_strdup(secret->iv); 320 } 321 322 323 static void 324 qcrypto_secret_prop_set_keyid(Object *obj, 325 const char *value, 326 Error **errp) 327 { 328 QCryptoSecret *secret = QCRYPTO_SECRET(obj); 329 330 g_free(secret->keyid); 331 secret->keyid = g_strdup(value); 332 } 333 334 335 static char * 336 qcrypto_secret_prop_get_keyid(Object *obj, 337 Error **errp) 338 { 339 QCryptoSecret *secret = QCRYPTO_SECRET(obj); 340 return g_strdup(secret->keyid); 341 } 342 343 344 static void 345 qcrypto_secret_complete(UserCreatable *uc, Error **errp) 346 { 347 object_property_set_bool(OBJECT(uc), true, "loaded", errp); 348 } 349 350 351 static void 352 qcrypto_secret_finalize(Object *obj) 353 { 354 QCryptoSecret *secret = QCRYPTO_SECRET(obj); 355 356 g_free(secret->iv); 357 g_free(secret->file); 358 g_free(secret->keyid); 359 g_free(secret->rawdata); 360 g_free(secret->data); 361 } 362 363 static void 364 qcrypto_secret_class_init(ObjectClass *oc, void *data) 365 { 366 UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc); 367 368 ucc->complete = qcrypto_secret_complete; 369 370 object_class_property_add_bool(oc, "loaded", 371 qcrypto_secret_prop_get_loaded, 372 qcrypto_secret_prop_set_loaded); 373 object_class_property_add_enum(oc, "format", 374 "QCryptoSecretFormat", 375 &QCryptoSecretFormat_lookup, 376 qcrypto_secret_prop_get_format, 377 qcrypto_secret_prop_set_format); 378 object_class_property_add_str(oc, "data", 379 qcrypto_secret_prop_get_data, 380 qcrypto_secret_prop_set_data); 381 object_class_property_add_str(oc, "file", 382 qcrypto_secret_prop_get_file, 383 qcrypto_secret_prop_set_file); 384 object_class_property_add_str(oc, "keyid", 385 qcrypto_secret_prop_get_keyid, 386 qcrypto_secret_prop_set_keyid); 387 object_class_property_add_str(oc, "iv", 388 qcrypto_secret_prop_get_iv, 389 qcrypto_secret_prop_set_iv); 390 } 391 392 393 int qcrypto_secret_lookup(const char *secretid, 394 uint8_t **data, 395 size_t *datalen, 396 Error **errp) 397 { 398 Object *obj; 399 QCryptoSecret *secret; 400 401 obj = object_resolve_path_component( 402 object_get_objects_root(), secretid); 403 if (!obj) { 404 error_setg(errp, "No secret with id '%s'", secretid); 405 return -1; 406 } 407 408 secret = (QCryptoSecret *) 409 object_dynamic_cast(obj, 410 TYPE_QCRYPTO_SECRET); 411 if (!secret) { 412 error_setg(errp, "Object with id '%s' is not a secret", 413 secretid); 414 return -1; 415 } 416 417 if (!secret->rawdata) { 418 error_setg(errp, "Secret with id '%s' has no data", 419 secretid); 420 return -1; 421 } 422 423 *data = g_new0(uint8_t, secret->rawlen + 1); 424 memcpy(*data, secret->rawdata, secret->rawlen); 425 (*data)[secret->rawlen] = '\0'; 426 *datalen = secret->rawlen; 427 428 return 0; 429 } 430 431 432 char *qcrypto_secret_lookup_as_utf8(const char *secretid, 433 Error **errp) 434 { 435 uint8_t *data; 436 size_t datalen; 437 438 if (qcrypto_secret_lookup(secretid, 439 &data, 440 &datalen, 441 errp) < 0) { 442 return NULL; 443 } 444 445 if (!g_utf8_validate((const gchar*)data, datalen, NULL)) { 446 error_setg(errp, 447 "Data from secret %s is not valid UTF-8", 448 secretid); 449 g_free(data); 450 return NULL; 451 } 452 453 return (char *)data; 454 } 455 456 457 char *qcrypto_secret_lookup_as_base64(const char *secretid, 458 Error **errp) 459 { 460 uint8_t *data; 461 size_t datalen; 462 char *ret; 463 464 if (qcrypto_secret_lookup(secretid, 465 &data, 466 &datalen, 467 errp) < 0) { 468 return NULL; 469 } 470 471 ret = g_base64_encode(data, datalen); 472 g_free(data); 473 return ret; 474 } 475 476 477 static const TypeInfo qcrypto_secret_info = { 478 .parent = TYPE_OBJECT, 479 .name = TYPE_QCRYPTO_SECRET, 480 .instance_size = sizeof(QCryptoSecret), 481 .instance_finalize = qcrypto_secret_finalize, 482 .class_size = sizeof(QCryptoSecretClass), 483 .class_init = qcrypto_secret_class_init, 484 .interfaces = (InterfaceInfo[]) { 485 { TYPE_USER_CREATABLE }, 486 { } 487 } 488 }; 489 490 491 static void 492 qcrypto_secret_register_types(void) 493 { 494 type_register_static(&qcrypto_secret_info); 495 } 496 497 498 type_init(qcrypto_secret_register_types); 499