1 /* secrets.c 2 * Secrets management and processing. 3 * Copyright 2018, Peter Wu <peter@lekensteyn.nl> 4 * 5 * Wireshark - Network traffic analyzer 6 * By Gerald Combs <gerald@wireshark.org> 7 * Copyright 1998 Gerald Combs 8 * 9 * SPDX-License-Identifier: GPL-2.0-or-later 10 */ 11 12 #include "config.h" 13 14 #define WS_LOG_DOMAIN LOG_DOMAIN_EPAN 15 16 #include "secrets.h" 17 #include <wiretap/wtap.h> 18 #include <wsutil/glib-compat.h> 19 #include <wsutil/wslog.h> 20 21 #include <string.h> 22 #ifdef HAVE_LIBGNUTLS 23 # include <gnutls/gnutls.h> 24 # include <gnutls/abstract.h> 25 # include <wsutil/wsgcrypt.h> 26 # include <wsutil/rsa.h> 27 # include <epan/uat.h> 28 # include <wsutil/report_message.h> 29 # include <wsutil/file_util.h> 30 # include <errno.h> 31 # if GNUTLS_VERSION_NUMBER < 0x030401 32 # define GNUTLS_KEYID_USE_SHA1 0 33 # endif 34 #endif /* HAVE_LIBGNUTLS */ 35 36 /** Maps guint32 secrets_type -> secrets_block_callback_t. */ 37 static GHashTable *secrets_callbacks; 38 39 #ifdef HAVE_LIBGNUTLS 40 /** Maps public key IDs (cert_key_id_t) -> gnutls_privkey_t. */ 41 static GHashTable *rsa_privkeys; 42 43 typedef struct { 44 char *uri; /**< User-supplied PKCS #11 URI for token or RSA private key file. */ 45 char *password; /**< User-supplied PKCS #11 PIN or RSA private key file password. */ 46 } rsa_privkey_record_t; 47 48 static uat_t *rsa_privkeys_uat; 49 static rsa_privkey_record_t *uat_rsa_privkeys; 50 static guint uat_num_rsa_privkeys; 51 52 static void register_rsa_uats(void); 53 #endif /* HAVE_LIBGNUTLS */ 54 55 #ifdef HAVE_GNUTLS_PKCS11 56 /** PINs for PKCS #11 keys in rsa_privkeys. Must be cleared after rsa_privkeys. */ 57 static GSList *rsa_privkeys_pkcs11_pins; 58 59 typedef struct { 60 char *library_path; /**< PKCS #11 library path. */ 61 } pkcs11_lib_record_t; 62 63 static uat_t *pkcs11_libs_uat; 64 static pkcs11_lib_record_t *uat_pkcs11_libs; 65 static guint uat_num_pkcs11_libs; 66 #endif /* HAVE_GNUTLS_PKCS11 */ 67 68 void 69 secrets_init(void) 70 { 71 secrets_callbacks = g_hash_table_new(g_direct_hash, g_direct_equal); 72 #ifdef HAVE_LIBGNUTLS 73 rsa_privkeys = privkey_hash_table_new(); 74 register_rsa_uats(); 75 #endif /* HAVE_LIBGNUTLS */ 76 } 77 78 void 79 secrets_cleanup(void) 80 { 81 g_hash_table_destroy(secrets_callbacks); 82 secrets_callbacks = NULL; 83 #ifdef HAVE_LIBGNUTLS 84 g_hash_table_destroy(rsa_privkeys); 85 rsa_privkeys = NULL; 86 #ifdef HAVE_GNUTLS_PKCS11 87 g_slist_free_full(rsa_privkeys_pkcs11_pins, g_free); 88 rsa_privkeys_pkcs11_pins = NULL; 89 #endif /* HAVE_GNUTLS_PKCS11 */ 90 #endif /* HAVE_LIBGNUTLS */ 91 } 92 93 void 94 secrets_register_type(guint32 secrets_type, secrets_block_callback_t cb) 95 { 96 g_hash_table_insert(secrets_callbacks, GUINT_TO_POINTER(secrets_type), (gpointer)cb); 97 } 98 99 void 100 secrets_wtap_callback(guint32 secrets_type, const void *secrets, guint size) 101 { 102 secrets_block_callback_t cb = (secrets_block_callback_t)g_hash_table_lookup( 103 secrets_callbacks, GUINT_TO_POINTER(secrets_type)); 104 if (cb) { 105 cb(secrets, size); 106 } 107 } 108 109 #ifdef HAVE_LIBGNUTLS 110 static guint 111 key_id_hash(gconstpointer key) 112 { 113 const cert_key_id_t *key_id = (const cert_key_id_t *)key; 114 const guint32 *dw = (const guint32 *)key_id->key_id; 115 116 /* The public key' SHA-1 hash (which maps to a private key) has a uniform 117 * distribution, hence simply xor'ing them should be sufficient. */ 118 return dw[0] ^ dw[1] ^ dw[2] ^ dw[3] ^ dw[4]; 119 } 120 121 static gboolean 122 key_id_equal(gconstpointer a, gconstpointer b) 123 { 124 const cert_key_id_t *key_id_a = (const cert_key_id_t *)a; 125 const cert_key_id_t *key_id_b = (const cert_key_id_t *)b; 126 127 return !memcmp(key_id_a, key_id_b, sizeof(*key_id_a)); 128 } 129 130 GHashTable * 131 privkey_hash_table_new(void) 132 { 133 return g_hash_table_new_full(key_id_hash, key_id_equal, g_free, (GDestroyNotify)gnutls_privkey_deinit); 134 } 135 136 static void 137 rsa_privkey_add(const cert_key_id_t *key_id, gnutls_privkey_t pkey) 138 { 139 void *ht_key = g_memdup2(key_id->key_id, sizeof(cert_key_id_t)); 140 const guint32 *dw = (const guint32 *)key_id->key_id; 141 g_hash_table_insert(rsa_privkeys, ht_key, pkey); 142 ws_debug("Adding RSA private, Key ID %08x%08x%08x%08x%08x", g_htonl(dw[0]), 143 g_htonl(dw[1]), g_htonl(dw[2]), g_htonl(dw[3]), g_htonl(dw[4])); 144 } 145 146 #ifdef HAVE_GNUTLS_PKCS11 147 /** Provides a fixed PIN to the caller (or failure if the fixed PIN is NULL). */ 148 static int 149 set_pin_callback(void *userdata, int attempt _U_, 150 const char *token_url _U_, const char *token_label _U_, 151 unsigned int flags, char *pin, size_t pin_max) 152 { 153 const char *fixed_pin = (const char *)userdata; 154 size_t fixed_pin_len = fixed_pin ? strlen(fixed_pin) : 0; 155 156 /* Fail if the PIN was not provided, wrong or too long. */ 157 if (!fixed_pin || (flags & GNUTLS_PIN_WRONG) || fixed_pin_len >= pin_max) { 158 return GNUTLS_E_PKCS11_PIN_ERROR; 159 } 160 161 memcpy(pin, fixed_pin, fixed_pin_len + 1); 162 return 0; 163 } 164 165 static GSList * 166 get_pkcs11_token_uris(void) 167 { 168 GSList *tokens = NULL; 169 170 for (unsigned i = 0; ; i++) { 171 char *uri = NULL; 172 int flags; 173 int ret = gnutls_pkcs11_token_get_url(i, GNUTLS_PKCS11_URL_GENERIC, &uri); 174 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { 175 break; 176 } 177 178 if (ret < 0) { 179 ws_debug("Failed to query token %u: %s\n", i, gnutls_strerror(ret)); 180 break; 181 } 182 183 ret = gnutls_pkcs11_token_get_flags(uri, &flags); 184 if (ret < 0) { 185 ws_debug("Failed to query token flags for %s: %s\n", uri, gnutls_strerror(ret)); 186 gnutls_free(uri); 187 continue; 188 } 189 190 // The "Trust module" is useless for decryption, so do not return it. 191 if ((flags & GNUTLS_PKCS11_TOKEN_TRUSTED)) { 192 gnutls_free(uri); 193 continue; 194 } 195 196 tokens = g_slist_prepend(tokens, g_strdup(uri)); 197 gnutls_free(uri); 198 } 199 200 tokens = g_slist_reverse(tokens); 201 202 return tokens; 203 } 204 205 static gboolean 206 verify_pkcs11_token(const char *token_uri, const char *pin, gboolean *pin_needed, char **error) 207 { 208 gnutls_pkcs11_obj_t *list = NULL; 209 unsigned int nlist = 0; 210 int ret; 211 212 /* Set PIN via a global callback since import_url can prompt for one. */ 213 gnutls_pkcs11_set_pin_function(set_pin_callback, (void *)pin); 214 215 /* This should ask for a PIN if needed. If no PIN is given, 216 * GNUTLS_E_PKCS11_PIN_ERROR (-303) is returned. */ 217 ret = gnutls_pkcs11_obj_list_import_url4(&list, &nlist, token_uri, 218 GNUTLS_PKCS11_OBJ_FLAG_PRIVKEY|GNUTLS_PKCS11_OBJ_FLAG_LOGIN); 219 if (ret == 0) { 220 /* Do not care about the objects, we just wanted to know whether the 221 * token and PIN were valid. */ 222 for (unsigned i = 0; i < nlist; i++) { 223 gnutls_pkcs11_obj_deinit(list[i]); 224 } 225 gnutls_free(list); 226 } 227 228 /* Forget about the PIN. */ 229 gnutls_pkcs11_set_pin_function(NULL, NULL); 230 231 if (pin_needed) { 232 *pin_needed = ret == GNUTLS_E_PKCS11_PIN_ERROR; 233 } 234 if (ret != 0) { 235 if (error) { 236 *error = g_strdup(gnutls_strerror(ret)); 237 } 238 return FALSE; 239 } 240 return TRUE; 241 } 242 243 /** 244 * Load private RSA keys from a PKCS #11 token. Returns zero on success and a 245 * negative error code on failure. 246 */ 247 static int 248 pkcs11_load_keys_from_token(const char *token_uri, const char *pin, char **err) 249 { 250 gnutls_pkcs11_obj_t *list = NULL; 251 unsigned int nlist = 0; 252 int ret; 253 /* An empty/NULL PIN means that none is necessary. */ 254 char *fixed_pin = pin && pin[0] ? g_strdup(pin) : NULL; 255 gboolean pin_in_use = FALSE; 256 257 /* Set PIN via a global callback since import_url can prompt for one. */ 258 gnutls_pkcs11_set_pin_function(set_pin_callback, fixed_pin); 259 260 /* This might already result in callback for the PIN. */ 261 ret = gnutls_pkcs11_obj_list_import_url4(&list, &nlist, token_uri, 262 GNUTLS_PKCS11_OBJ_FLAG_PRIVKEY|GNUTLS_PKCS11_OBJ_FLAG_LOGIN); 263 if (ret < 0) { 264 *err = g_strdup_printf("Failed to iterate through objects for %s: %s", token_uri, gnutls_strerror(ret)); 265 goto cleanup; 266 } 267 268 for (unsigned j = 0; j < nlist; j++) { 269 char *obj_uri = NULL; 270 gnutls_privkey_t privkey = NULL; 271 gnutls_pubkey_t pubkey = NULL; 272 cert_key_id_t key_id; 273 size_t size; 274 275 if (gnutls_pkcs11_obj_get_type(list[j]) != GNUTLS_PKCS11_OBJ_PRIVKEY) { 276 /* Should not happen since we requested private keys only. */ 277 goto cont; 278 } 279 280 ret = gnutls_pkcs11_obj_export_url(list[j], GNUTLS_PKCS11_URL_GENERIC, &obj_uri); 281 if (ret < 0) { 282 /* Should not happen either if the object is valid. */ 283 goto cont; 284 } 285 286 ret = gnutls_privkey_init(&privkey); 287 if (ret < 0) { 288 /* Out of memory? */ 289 goto cont; 290 } 291 292 /* Set the PIN to be used during decryption. */ 293 gnutls_privkey_set_pin_function(privkey, set_pin_callback, fixed_pin); 294 295 /* Can prompt for PIN. Can also invoke the token function set by 296 * gnutls_pkcs11_set_token_function (if not set, it will just fail 297 * immediately rather than retrying). */ 298 ret = gnutls_privkey_import_url(privkey, obj_uri, 0); 299 if (ret < 0) { 300 /* Bad PIN or some other system error? */ 301 ws_debug("Failed to import private key %s: %s", obj_uri, gnutls_strerror(ret)); 302 goto cont; 303 } 304 305 if (gnutls_privkey_get_pk_algorithm(privkey, NULL) != GNUTLS_PK_RSA) { 306 ws_debug("Skipping private key %s, not RSA.", obj_uri); 307 goto cont; 308 } 309 310 ret = gnutls_pubkey_init(&pubkey); 311 if (ret < 0) { 312 /* Out of memory? */ 313 goto cont; 314 } 315 316 /* This requires GnuTLS 3.4.0 and will fail on older versions. */ 317 ret = gnutls_pubkey_import_privkey(pubkey, privkey, 0, 0); 318 if (ret < 0) { 319 ws_debug("Failed to import public key %s: %s", obj_uri, gnutls_strerror(ret)); 320 goto cont; 321 } 322 323 size = sizeof(key_id); 324 ret = gnutls_pubkey_get_key_id(pubkey, GNUTLS_KEYID_USE_SHA1, key_id.key_id, &size); 325 if (ret < 0 || size != sizeof(key_id)) { 326 ws_debug("Failed to calculate Key ID for %s: %s", obj_uri, gnutls_strerror(ret)); 327 goto cont; 328 } 329 330 /* Remember the private key. */ 331 rsa_privkey_add(&key_id, privkey); 332 privkey = NULL; 333 pin_in_use = TRUE; 334 335 cont: 336 gnutls_privkey_deinit(privkey); 337 gnutls_pubkey_deinit(pubkey); 338 gnutls_free(obj_uri); 339 gnutls_pkcs11_obj_deinit(list[j]); 340 } 341 gnutls_free(list); 342 if (pin_in_use) { 343 /* Remember PINs such they can be freed later. */ 344 rsa_privkeys_pkcs11_pins = g_slist_prepend(rsa_privkeys_pkcs11_pins, fixed_pin); 345 fixed_pin = NULL; 346 } 347 ret = 0; 348 349 cleanup: 350 /* Forget about the PIN. */ 351 gnutls_pkcs11_set_pin_function(NULL, NULL); 352 g_free(fixed_pin); 353 return ret; 354 } 355 356 /** Load all libraries specified in a UAT. */ 357 static void 358 uat_pkcs11_libs_load_all(void) 359 { 360 int ret; 361 GString *err = NULL; 362 363 for (guint i = 0; i < uat_num_pkcs11_libs; i++) { 364 const pkcs11_lib_record_t *rec = &uat_pkcs11_libs[i]; 365 const char *libname = rec->library_path; 366 #ifdef WIN32 367 // Work around a bug in p11-kit < 0.23.16 on Windows 368 HMODULE provider_lib = LoadLibraryA(libname); 369 if (! provider_lib || ! GetProcAddress(provider_lib, "C_GetFunctionList")) { 370 ret = GNUTLS_E_PKCS11_LOAD_ERROR; 371 } else { 372 #endif 373 /* Note: should return success for already loaded libraries. */ 374 ret = gnutls_pkcs11_add_provider(libname, NULL); 375 #ifdef WIN32 376 } 377 if (provider_lib) { 378 FreeLibrary(provider_lib); 379 } 380 #endif 381 if (ret) { 382 if (!err) { 383 err = g_string_new("Error loading PKCS #11 libraries:"); 384 } 385 g_string_append_printf(err, "\n%s: %s", libname, gnutls_strerror(ret)); 386 } 387 } 388 if (err) { 389 report_failure("%s", err->str); 390 g_string_free(err, TRUE); 391 } 392 } 393 394 UAT_FILENAME_CB_DEF(pkcs11_libs_uats, library_path, pkcs11_lib_record_t) 395 396 static void * 397 uat_pkcs11_lib_copy_str_cb(void *dest, const void *source, size_t len _U_) 398 { 399 pkcs11_lib_record_t *d = (pkcs11_lib_record_t *)dest; 400 const pkcs11_lib_record_t *s = (const pkcs11_lib_record_t *)source; 401 d->library_path = g_strdup(s->library_path); 402 return dest; 403 } 404 405 static void 406 uat_pkcs11_lib_free_str_cb(void *record) 407 { 408 pkcs11_lib_record_t *rec = (pkcs11_lib_record_t *)record; 409 g_free(rec->library_path); 410 } 411 #endif /* HAVE_GNUTLS_PKCS11 */ 412 413 UAT_FILENAME_CB_DEF(rsa_privkeys_uats, uri, rsa_privkey_record_t) 414 UAT_CSTRING_CB_DEF(rsa_privkeys_uats, password, rsa_privkey_record_t) 415 416 static void * 417 uat_rsa_privkey_copy_str_cb(void *dest, const void *source, size_t len _U_) 418 { 419 rsa_privkey_record_t *d = (rsa_privkey_record_t *)dest; 420 const rsa_privkey_record_t *s = (const rsa_privkey_record_t *)source; 421 d->uri = g_strdup(s->uri); 422 d->password = g_strdup(s->password); 423 return dest; 424 } 425 426 static void 427 uat_rsa_privkey_free_str_cb(void *record) 428 { 429 rsa_privkey_record_t *rec = (rsa_privkey_record_t *)record; 430 g_free(rec->uri); 431 g_free(rec->password); 432 } 433 434 static void 435 load_rsa_keyfile(const char *filename, const char *password, gboolean save_key, char **err) 436 { 437 gnutls_x509_privkey_t x509_priv_key; 438 gnutls_privkey_t privkey = NULL; 439 char *errmsg = NULL; 440 int ret; 441 cert_key_id_t key_id; 442 size_t size = sizeof(key_id); 443 444 FILE *fp = ws_fopen(filename, "rb"); 445 if (!fp) { 446 *err = g_strdup_printf("Error loading RSA key file %s: %s", filename, g_strerror(errno)); 447 return; 448 } 449 450 if (!password || !password[0]) { 451 x509_priv_key = rsa_load_pem_key(fp, &errmsg); 452 } else { 453 /* Assume encrypted PKCS #12 container. */ 454 x509_priv_key = rsa_load_pkcs12(fp, password, &errmsg); 455 } 456 fclose(fp); 457 if (!x509_priv_key) { 458 *err = g_strdup_printf("Error loading RSA key file %s: %s", filename, errmsg); 459 g_free(errmsg); 460 return; 461 } 462 463 gnutls_privkey_init(&privkey); 464 ret = gnutls_privkey_import_x509(privkey, x509_priv_key, 465 GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE|GNUTLS_PRIVKEY_IMPORT_COPY); 466 if (ret < 0) { 467 *err = g_strdup_printf("Error importing private key %s: %s", filename, gnutls_strerror(ret)); 468 goto end; 469 } 470 ret = gnutls_x509_privkey_get_key_id(x509_priv_key, GNUTLS_KEYID_USE_SHA1, key_id.key_id, &size); 471 if (ret < 0 || size != sizeof(key_id)) { 472 *err = g_strdup_printf("Error calculating Key ID for %s: %s", filename, gnutls_strerror(ret)); 473 goto end; 474 } 475 476 /* Remember the private key. */ 477 if (save_key) { 478 rsa_privkey_add(&key_id, privkey); 479 privkey = NULL; 480 } 481 482 end: 483 gnutls_x509_privkey_deinit(x509_priv_key); 484 gnutls_privkey_deinit(privkey); 485 } 486 487 static void 488 uat_rsa_privkeys_post_update(void) 489 { 490 /* Clear previous keys. */ 491 g_hash_table_remove_all(rsa_privkeys); 492 #ifdef HAVE_GNUTLS_PKCS11 493 g_slist_free_full(rsa_privkeys_pkcs11_pins, g_free); 494 rsa_privkeys_pkcs11_pins = NULL; 495 #endif /* HAVE_GNUTLS_PKCS11 */ 496 GString *errors = NULL; 497 498 for (guint i = 0; i < uat_num_rsa_privkeys; i++) { 499 const rsa_privkey_record_t *rec = &uat_rsa_privkeys[i]; 500 const char *token_uri = rec->uri; 501 char *err = NULL; 502 503 if (g_str_has_prefix(token_uri, "pkcs11:")) { 504 #ifdef HAVE_GNUTLS_PKCS11 505 pkcs11_load_keys_from_token(token_uri, rec->password, &err); 506 #endif /* HAVE_GNUTLS_PKCS11 */ 507 } else { 508 load_rsa_keyfile(token_uri, rec->password, TRUE, &err); 509 } 510 if (err) { 511 if (!errors) { 512 errors = g_string_new("Error processing rsa_privkeys:"); 513 } 514 g_string_append_c(errors, '\n'); 515 g_string_append(errors, err); 516 g_free(err); 517 } 518 } 519 if (errors) { 520 report_failure("%s", errors->str); 521 g_string_free(errors, TRUE); 522 } 523 } 524 525 GSList * 526 secrets_get_available_keys(void) 527 { 528 GSList *keys = NULL; 529 #ifdef HAVE_GNUTLS_PKCS11 530 keys = g_slist_concat(keys, get_pkcs11_token_uris()); 531 #endif 532 return keys; 533 } 534 535 gboolean 536 secrets_verify_key(const char *uri, const char *password, gboolean *need_password, char **error) 537 { 538 if (need_password) { 539 *need_password = FALSE; 540 } 541 if (error) { 542 *error = NULL; 543 } 544 545 if (g_str_has_prefix(uri, "pkcs11:")) { 546 #ifdef HAVE_GNUTLS_PKCS11 547 return verify_pkcs11_token(uri, password, need_password, error); 548 #else 549 if (error) { 550 *error = g_strdup("PKCS #11 support is not available in this build"); 551 } 552 return FALSE; 553 #endif 554 } else if (g_file_test(uri, G_FILE_TEST_IS_REGULAR)) { 555 gchar *err = NULL; 556 load_rsa_keyfile(uri, password, FALSE, &err); 557 if (need_password) { 558 // Assume that failure to load the key is due to password errors. 559 // This might not be correct, but fixing this needs more changes. 560 *need_password = err != NULL; 561 } 562 if (err) { 563 if (error) { 564 *error = err; 565 } else { 566 g_free(err); 567 } 568 return FALSE; 569 } 570 return TRUE; 571 } else { 572 if (error) { 573 *error = g_strdup("Unsupported key URI or path"); 574 } 575 return FALSE; 576 } 577 } 578 579 /** 580 * Register the UAT definitions such that settings can be loaded from file. 581 * Note: relies on uat_load_all to invoke the post_update_cb in order of 582 * registration below such that libraries are loaded *before* keys are read. 583 */ 584 static void 585 register_rsa_uats(void) 586 { 587 #ifdef HAVE_GNUTLS_PKCS11 588 static uat_field_t uat_pkcs11_libs_fields[] = { 589 UAT_FLD_FILENAME_OTHER(pkcs11_libs_uats, library_path, "Library Path", NULL, "PKCS #11 provider library file"), 590 UAT_END_FIELDS 591 }; 592 pkcs11_libs_uat = uat_new("PKCS #11 Provider Libraries", 593 sizeof(pkcs11_lib_record_t), 594 "pkcs11_libs", /* filename */ 595 FALSE, /* from_profile */ 596 &uat_pkcs11_libs, /* data_ptr */ 597 &uat_num_pkcs11_libs, /* numitems_ptr */ 598 0, /* does not directly affect dissection */ 599 NULL, /* Help section (currently a wiki page) */ 600 uat_pkcs11_lib_copy_str_cb, /* copy_cb */ 601 NULL, /* update_cb */ 602 uat_pkcs11_lib_free_str_cb, /* free_cb */ 603 uat_pkcs11_libs_load_all, /* post_update_cb */ 604 NULL, /* reset_cb */ 605 uat_pkcs11_libs_fields); 606 #endif /* HAVE_GNUTLS_PKCS11 */ 607 608 static uat_field_t uat_rsa_privkeys_fields[] = { 609 UAT_FLD_FILENAME_OTHER(rsa_privkeys_uats, uri, "Keyfile or Token URI", NULL, "RSA Key File or PKCS #11 URI for token"), 610 UAT_FLD_FILENAME_OTHER(rsa_privkeys_uats, password, "Password", NULL, "RSA Key File password or PKCS #11 Token PIN"), 611 UAT_END_FIELDS 612 }; 613 rsa_privkeys_uat = uat_new("RSA Private Keys", 614 sizeof(rsa_privkey_record_t), 615 "rsa_keys", /* filename */ 616 FALSE, /* from_profile */ 617 &uat_rsa_privkeys, /* data_ptr */ 618 &uat_num_rsa_privkeys, /* numitems_ptr */ 619 0, /* does not directly affect dissection */ 620 NULL, /* Help section (currently a wiki page) */ 621 uat_rsa_privkey_copy_str_cb, /* copy_cb */ 622 NULL, /* update_cb */ 623 uat_rsa_privkey_free_str_cb, /* free_cb */ 624 uat_rsa_privkeys_post_update, /* post_update_cb */ 625 NULL, /* reset_cb */ 626 uat_rsa_privkeys_fields); 627 } 628 629 int 630 secrets_rsa_decrypt(const cert_key_id_t *key_id, const guint8 *encr, int encr_len, guint8 **out, int *out_len) 631 { 632 gboolean ret; 633 gnutls_datum_t ciphertext = { (guchar *)encr, encr_len }; 634 gnutls_datum_t plain = { 0 }; 635 636 gnutls_privkey_t pkey = (gnutls_privkey_t)g_hash_table_lookup(rsa_privkeys, key_id->key_id); 637 if (!pkey) { 638 return GNUTLS_E_NO_CERTIFICATE_FOUND; 639 } 640 641 ret = gnutls_privkey_decrypt_data(pkey, 0, &ciphertext, &plain); 642 if (ret == 0) { 643 *out = (guint8 *)g_memdup2(plain.data, plain.size); 644 *out_len = plain.size; 645 gnutls_free(plain.data); 646 } 647 648 return ret; 649 } 650 #endif /* HAVE_LIBGNUTLS */ 651 652 /* 653 * Editor modelines - https://www.wireshark.org/tools/modelines.html 654 * 655 * Local variables: 656 * c-basic-offset: 4 657 * tab-width: 8 658 * indent-tabs-mode: nil 659 * End: 660 * 661 * vi: set shiftwidth=4 tabstop=8 expandtab: 662 * :indentSize=4:tabSize=8:noTabs=true: 663 */ 664