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