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