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