1 /* NSS keys for the Pidgin-Encryption plugin */ 2 /* Copyright (C) 2001 William Tompkins */ 3 4 /* This plugin is free software, distributed under the GNU General Public */ 5 /* License. */ 6 /* Please see the file "COPYING" distributed with this source code */ 7 /* for more details */ 8 /* */ 9 /* */ 10 /* This software is distributed in the hope that it will be useful, */ 11 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ 12 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ 13 /* General Public License for more details. */ 14 15 /* To compile and use: */ 16 /* See INSTALL file. */ 17 18 #include "internal.h" 19 20 #include <gdk/gdk.h> 21 #include <gtk/gtk.h> 22 #include <gtk/gtkplug.h> 23 24 #include <debug.h> 25 #include <gtkdialogs.h> 26 27 #include "glib.h" 28 29 #include <string.h> 30 #include <assert.h> 31 32 #ifdef _WIN32 33 #include "win32dep.h" 34 #endif 35 36 #include "rsa_nss.h" 37 38 #include <nspr.h> 39 #include <nss.h> 40 #include <ssl.h> 41 #include <secmod.h> 42 #include <pk11func.h> 43 #include <keyhi.h> 44 #include <nssb64.h> 45 46 47 #include "nls.h" 48 #include "nss_mgf1.h" 49 #include "nss_oaep.h" 50 #include "nss_pss.h" 51 #include "cryptutil.h" 52 #include "keys.h" 53 #include "cryptproto.h" 54 #include "state_ui.h" 55 56 char* rsa_nss_proto_string="NSS 1.0"; 57 58 crypt_proto* rsa_nss_proto; 59 60 /*Functions exported through crypt_proto structure */ 61 static int rsa_nss_encrypt(unsigned char**, unsigned char*, int, crypt_key*); 62 static int rsa_nss_decrypt(unsigned char**, unsigned char*, int, crypt_key*); 63 static int rsa_nss_sign(unsigned char**, unsigned char*, int, crypt_key*, crypt_key*); 64 static int rsa_nss_auth(unsigned char**, unsigned char*, int, crypt_key*, const char* name); 65 static crypt_key* rsa_nss_make_key_from_str(char *key_str); 66 static GString* rsa_nss_key_to_gstr(crypt_key* inkey); 67 static char* rsa_nss_parseable(char* key); 68 static crypt_key* rsa_nss_parse_sent_key(char *key_str); 69 static GString* rsa_nss_make_sendable_key(crypt_key* inkey, const char* name); 70 static gchar* rsa_nss_make_key_id(crypt_key* inkey); 71 72 void rsa_nss_gen_key_pair(crypt_key **, crypt_key **, 73 const char* name, int keysize); 74 static void rsa_nss_free(crypt_key*); 75 static crypt_key* rsa_nss_make_pub_from_priv(crypt_key* priv); 76 static int rsa_nss_calc_unencrypted_size(struct crypt_key*, int); 77 static int rsa_nss_calc_unsigned_size(struct crypt_key*, int); 78 79 /* internals */ 80 void rsa_nss_test(crypt_key *pub, crypt_key *priv); 81 82 83 gboolean rsa_nss_init() { 84 85 gboolean nss_loaded_ok = FALSE; 86 87 PurplePlugin *plugin = purple_plugins_find_with_name("NSS"); 88 89 if (plugin != NULL) { 90 nss_loaded_ok = purple_plugin_is_loaded(plugin); 91 if (!nss_loaded_ok) { 92 nss_loaded_ok = purple_plugin_load(plugin); 93 } 94 } 95 96 if (!nss_loaded_ok) { 97 purple_debug(PURPLE_DEBUG_ERROR, "pidgin-encryption", "Initializing NSS without Purple support\n"); 98 /* Purple doesn't seem to have NSS support: try to load it ourselves: */ 99 PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); 100 NSS_NoDB_Init(NULL); 101 102 /* TODO: Fix this so autoconf does the work trying to find this lib. */ 103 SECMOD_AddNewModule("Builtins", 104 #ifndef _WIN32 105 LIBDIR "/libnssckbi.so", 106 #else 107 "nssckbi.dll", 108 #endif 109 0, 0); 110 NSS_SetDomesticPolicy(); 111 112 /* purple_debug(PURPLE_DEBUG_ERROR, "pidgin-encryption", _("Can't load the NSS plugin\n")); */ 113 /* PE_error_window(_("Purple was not compiled with the NSS plugin enabled. " */ 114 /* "Pidgin-Encryption requires the NSS plugin to function.")); */ 115 /* return FALSE; */ 116 } 117 118 rsa_nss_proto = g_malloc(sizeof(crypt_proto)); 119 crypt_proto_list = g_slist_prepend(crypt_proto_list, rsa_nss_proto); 120 121 rsa_nss_proto->encrypt = rsa_nss_encrypt; 122 rsa_nss_proto->decrypt = rsa_nss_decrypt; 123 rsa_nss_proto->sign = rsa_nss_sign; 124 rsa_nss_proto->auth = rsa_nss_auth; 125 126 rsa_nss_proto->make_key_from_str = rsa_nss_make_key_from_str; 127 rsa_nss_proto->key_to_gstr = rsa_nss_key_to_gstr; 128 rsa_nss_proto->parseable = rsa_nss_parseable; 129 rsa_nss_proto->parse_sent_key = rsa_nss_parse_sent_key; 130 rsa_nss_proto->make_sendable_key = rsa_nss_make_sendable_key; 131 rsa_nss_proto->make_key_id = rsa_nss_make_key_id; 132 rsa_nss_proto->gen_key_pair = rsa_nss_gen_key_pair; 133 rsa_nss_proto->free = rsa_nss_free; 134 rsa_nss_proto->make_pub_from_priv = rsa_nss_make_pub_from_priv; 135 rsa_nss_proto->calc_unencrypted_size = rsa_nss_calc_unencrypted_size; 136 rsa_nss_proto->calc_unsigned_size = rsa_nss_calc_unsigned_size; 137 rsa_nss_proto->name = rsa_nss_proto_string; 138 139 return TRUE; 140 } 141 142 static void rsa_nss_free(crypt_key* key){ 143 if (key->store.rsa_nss.pub) { 144 SECKEY_DestroyPublicKey(key->store.rsa_nss.pub); 145 key->store.rsa_nss.pub = 0; 146 } 147 if (key->store.rsa_nss.priv) { 148 SECKEY_DestroyPrivateKey(key->store.rsa_nss.priv); 149 key->store.rsa_nss.priv = 0; 150 } 151 } 152 153 static SECItem* 154 get_random_iv(CK_MECHANISM_TYPE mechType) 155 { 156 int iv_size = PK11_GetIVLength(mechType); 157 SECItem *iv; 158 SECStatus rv; 159 160 iv = PORT_ZNew(SECItem); 161 g_assert(iv != 0); 162 g_assert(iv_size != 0); 163 164 iv->data = PORT_NewArray(unsigned char, iv_size); 165 g_assert(iv->data != 0); 166 iv->len = iv_size; 167 rv = PK11_GenerateRandom(iv->data, iv->len); 168 g_assert(rv == SECSuccess); 169 170 return iv; 171 } 172 173 static void generate_digest(char* digest, SECKEYPublicKey* key) { 174 SECItem *hash = PK11_MakeIDFromPubKey(&key->u.rsa.modulus); 175 int i = 0, digestPos = 0; 176 177 while (i < hash->len && digestPos < KEY_DIGEST_LENGTH) { 178 sprintf(digest + digestPos, "%02x", hash->data[i]); 179 ++i; 180 digestPos += 2; 181 } 182 SECITEM_ZfreeItem (hash, PR_TRUE); 183 } 184 185 static void generate_fingerprint(char* print, SECKEYPublicKey* key) { 186 SECItem *hash = PK11_MakeIDFromPubKey(&key->u.rsa.modulus); 187 int i; 188 189 for (i= 0; i < hash->len - 1; ++i) { 190 sprintf(print + (3*i), "%02x:", hash->data[i]); 191 } 192 sprintf(print + 3 * (hash->len - 1), "%02x", hash->data[(hash->len - 1)]); 193 SECITEM_ZfreeItem (hash, PR_TRUE); 194 } 195 196 static SECKEYPublicKey * 197 copy_public_rsa_key(SECKEYPublicKey *pubk) { 198 SECKEYPublicKey *copyk; 199 PRArenaPool *arena; 200 SECStatus rv; 201 202 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 203 g_assert(arena != NULL); 204 205 copyk = (SECKEYPublicKey *) PORT_ArenaZAlloc (arena, sizeof (SECKEYPublicKey)); 206 g_assert(copyk != NULL); 207 208 copyk->arena = arena; 209 copyk->keyType = pubk->keyType; 210 211 copyk->pkcs11Slot = NULL; /* go get own reference */ 212 copyk->pkcs11ID = CK_INVALID_HANDLE; 213 214 rv = SECITEM_CopyItem(arena, ©k->u.rsa.modulus, 215 &pubk->u.rsa.modulus); 216 g_assert(rv == SECSuccess); 217 218 rv = SECITEM_CopyItem (arena, ©k->u.rsa.publicExponent, 219 &pubk->u.rsa.publicExponent); 220 g_assert(rv == SECSuccess); 221 222 return copyk; 223 } 224 225 void rsa_nss_gen_key_pair(crypt_key **pub_key, crypt_key **priv_key, 226 const char* name, int keysize) { 227 228 GtkWidget *status_window, *main_box, *label1, *label2; 229 char labelText[1000]; 230 PK11RSAGenParams rsaParams; 231 PK11SlotInfo *slot; 232 233 CK_MECHANISM_TYPE multiType[2] = {CKM_RSA_PKCS_KEY_PAIR_GEN, CKM_DES_CBC_PAD}; 234 235 /* Create the widgets */ 236 237 PIDGIN_DIALOG(status_window); 238 gtk_window_set_wmclass(GTK_WINDOW(status_window), "keygen", "Pidgin"); 239 gtk_widget_realize(status_window); 240 gtk_container_set_border_width(GTK_CONTAINER(status_window), 10); 241 gtk_widget_set_size_request(status_window, 350, 100); 242 gtk_window_set_title(GTK_WINDOW(status_window), "Status"); 243 main_box = gtk_vbox_new(FALSE, 0); 244 gtk_container_add(GTK_CONTAINER(status_window), main_box); 245 gtk_widget_show(main_box); 246 247 g_snprintf(labelText, sizeof(labelText), _("Generating RSA Key Pair for %s"), 248 name); 249 label1 = gtk_label_new (labelText); 250 label2 = gtk_label_new (_("This may take a little bit...")); 251 252 gtk_container_add (GTK_CONTAINER (main_box), label1); 253 gtk_widget_show(label1); 254 gtk_container_add (GTK_CONTAINER (main_box), label2); 255 gtk_widget_show(label2); 256 257 gtk_widget_show (status_window); 258 259 // I don't understand: if I remove one of these 260 // two loops, the contents of the status window don't 261 // get drawn. Hmm... 262 while (gtk_events_pending()) { 263 gtk_main_iteration_do(FALSE); 264 } 265 gtk_main_iteration(); 266 while (gtk_events_pending()) { 267 gtk_main_iteration_do(FALSE); 268 } 269 270 *priv_key = g_malloc(sizeof(crypt_key)); 271 272 rsaParams.keySizeInBits = keysize; 273 rsaParams.pe = 65537L; 274 275 slot = PK11_GetBestSlotMultiple(multiType, 2, 0); 276 277 /* Generate "session" (first FALSE), "not sensitive" (next FALSE) key */ 278 (*priv_key)->store.rsa_nss.priv = 279 PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, &rsaParams, 280 &(*priv_key)->store.rsa_nss.pub, 281 PR_FALSE, PR_FALSE, 0); 282 283 if (!(*priv_key)->store.rsa_nss.priv) { 284 purple_debug(PURPLE_DEBUG_ERROR, "pidgin-encryption", 285 _("Could not generate key. NSS Error: %d\n"), 286 PORT_GetError()); 287 exit(0); 288 } 289 290 (*priv_key)->proto = rsa_nss_proto; 291 g_snprintf((*priv_key)->length, sizeof((*priv_key)->length), "%d", keysize); 292 293 generate_digest((*priv_key)->digest, (*priv_key)->store.rsa_nss.pub); 294 generate_fingerprint((*priv_key)->fingerprint, (*priv_key)->store.rsa_nss.pub); 295 296 (*pub_key) = rsa_nss_make_pub_from_priv(*priv_key); 297 298 gtk_widget_hide(status_window); 299 gtk_widget_destroy(status_window); 300 } 301 302 char* rsa_nss_parseable(char *key) { 303 /* If the key is ours, return a pointer to the ':' after our token */ 304 /* otherwise return 0 */ 305 /* if we were more sophisticated, we could look for older versions */ 306 /* of our protocol here, and accept them too. */ 307 if (strncmp(rsa_nss_proto_string, key, strlen(rsa_nss_proto_string)) == 0) { 308 return key + strlen(rsa_nss_proto_string); 309 } else { 310 return 0; 311 } 312 } 313 314 315 static GString* append_priv_key_to_gstr(GString *str, SECKEYPrivateKey* priv) { 316 317 /* for now, we hope that everyone can use DES3. This is for wrapping */ 318 /* private keys, which isn't actually secure at this point anyways */ 319 /* (security provided by the OS: no one else can read/write the keyfile */ 320 const CK_MECHANISM_TYPE SymEncryptionType = CKM_DES3_CBC_PAD; 321 322 PK11SlotInfo *symSlot; 323 PK11SymKey *symKey; 324 325 SECItem symKeyItem; /* storage space for binary key import */ 326 unsigned char symKeyData[24] = {0}; 327 328 SECItem *iv = NULL; /* IV for CBC encoding */ 329 330 SECItem exportedKey; /* storage space for exported key */ 331 unsigned char exportedKeyData[5000] = {0}; 332 333 char* tmpstr; 334 int errCode; 335 336 if (priv == 0) return str; 337 338 /* Wrap key using a null symmetric key. When/If we add password protection to 339 keys, we can generate the symmetric key from a hashed password instead */ 340 symSlot = PK11_GetBestSlot(SymEncryptionType, NULL); 341 g_assert(symSlot != 0); 342 343 symKeyItem.data = &symKeyData[0]; 344 symKeyItem.len = sizeof(symKeyData); 345 346 symKey = PK11_ImportSymKey(symSlot, PK11_GetKeyGen(SymEncryptionType), 347 PK11_OriginUnwrap, CKA_WRAP, &symKeyItem, NULL); 348 349 iv = get_random_iv(SymEncryptionType); 350 351 exportedKey.len = sizeof(exportedKeyData); 352 exportedKey.data = exportedKeyData; 353 354 errCode = PK11_WrapPrivKey(symSlot, symKey, priv, SymEncryptionType, iv, 355 &exportedKey, NULL); 356 357 g_assert(errCode == SECSuccess); 358 359 360 g_string_append(str, ","); 361 362 tmpstr = NSSBase64_EncodeItem(0, 0, 0, iv); 363 g_string_append(str, tmpstr); 364 PORT_Free(tmpstr); 365 366 g_string_append(str, ","); 367 368 tmpstr = NSSBase64_EncodeItem(0, 0, 0, &exportedKey); 369 g_string_append(str, tmpstr); 370 PORT_Free(tmpstr); 371 372 g_string_append(str, ","); 373 374 PK11_FreeSymKey(symKey); 375 SECITEM_ZfreeItem(iv, PR_TRUE); 376 377 /* The Base64 routine may have inserted lots of return chars into the string: */ 378 /* take them out. */ 379 PE_strip_returns(str); 380 381 return str; 382 } 383 384 static GString* append_pub_key_to_gstr(GString *str, SECKEYPublicKey* pub) { 385 char *tmpstr; 386 SECItem *exportedKey; 387 388 if (pub == 0) return str; 389 390 exportedKey = SECKEY_EncodeDERSubjectPublicKeyInfo(pub); 391 // exportedKey = PK11_DEREncodePublicKey(pub); 392 393 tmpstr = NSSBase64_EncodeItem(0, 0, 0, exportedKey); 394 g_string_append(str, tmpstr); 395 396 PORT_Free(tmpstr); 397 SECITEM_FreeItem (exportedKey, PR_TRUE); 398 399 /* The Base64 routine may have inserted lots of return chars into the string: take them out. */ 400 PE_strip_returns(str); 401 402 return str; 403 } 404 405 406 GString* rsa_nss_make_sendable_key(crypt_key* inkey, const char* name) { 407 GString *outString = g_string_new(""); 408 409 gchar* nonce_str = PE_new_incoming_nonce(name); 410 g_string_append(outString, nonce_str); 411 412 purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "Sending Nonce with key: %s\n", nonce_str); 413 414 g_free(nonce_str); 415 416 g_string_append(outString, ","); 417 418 append_pub_key_to_gstr(outString, inkey->store.rsa_nss.pub); 419 420 return outString; 421 } 422 423 gchar* rsa_nss_make_key_id(crypt_key* inkey) { 424 return PE_nonce_to_str(&inkey->store.rsa_nss.nonce); 425 } 426 427 crypt_key* rsa_nss_parse_sent_key(char *key_str) { 428 gchar** split_key = g_strsplit(key_str, ",", 2); 429 crypt_key* key; 430 431 if ((split_key[0] == 0) || (split_key[1] == 0)) { 432 purple_debug(PURPLE_DEBUG_ERROR, "pidgin-encryption", "Error parsing RSANSS nonce/key\n"); 433 g_strfreev(split_key); 434 return 0; 435 } 436 437 key = rsa_nss_make_key_from_str(split_key[1]); 438 439 if (key == 0) { 440 g_strfreev(split_key); 441 return 0; 442 } 443 444 PE_str_to_nonce(&key->store.rsa_nss.nonce, split_key[0]); 445 purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "Received Nonce with key: %s\n", split_key[0]); 446 447 g_strfreev(split_key); 448 449 return key; 450 } 451 452 GString* rsa_nss_key_to_gstr(crypt_key* inkey) { 453 GString *outString = g_string_new(""); 454 455 append_pub_key_to_gstr(outString, inkey->store.rsa_nss.pub); 456 457 append_priv_key_to_gstr(outString, inkey->store.rsa_nss.priv); 458 459 return outString; 460 } 461 462 crypt_key* rsa_nss_make_key_from_str(char *key_str){ 463 gchar **split_key; 464 465 crypt_key* key = g_malloc(sizeof(crypt_key)); 466 467 /* For Private keys: */ 468 const CK_MECHANISM_TYPE SymEncryptionType = CKM_DES3_CBC_PAD; 469 PK11SlotInfo *symSlot; 470 PK11SymKey *symKey; 471 SECItem *pubKeyValue; 472 SECItem symKeyItem; /* storage space for binary key import */ 473 unsigned char symKeyData[24] = {0}; 474 SECItem *iv = 0, *wrappedKey = 0, label; 475 CK_ATTRIBUTE_TYPE attribs[3] = { CKA_SIGN, CKA_DECRYPT, CKA_SIGN_RECOVER }; 476 const int NumAttribs = 3; 477 int cur_piece; 478 479 CERTSubjectPublicKeyInfo *certPubKeyInfo; 480 481 /* key_str looks like "KKKKK" or "KKKKK,NNNN,MMMM", where */ 482 /* KKKKK is the Base64 encoding of the public key, or */ 483 /* NNNN is the Base64 encoding of the IV, and */ 484 /* MMMM is the Base64 encoding of the encrypted private key */ 485 486 487 key->proto = rsa_nss_proto; 488 489 split_key = g_strsplit(key_str, ",", 3); 490 491 key->store.rsa_nss.pub = 0; 492 key->store.rsa_nss.priv = 0; 493 494 cur_piece = 0; 495 496 // Check for public key part, and get it: 497 498 if (split_key[cur_piece] == 0) { 499 purple_debug(PURPLE_DEBUG_ERROR, "pidgin-encryption", "(%d) %s", 500 1, _("Error parsing RSANSS key\n")); 501 g_free(key); 502 g_strfreev(split_key); 503 return 0; 504 } 505 506 wrappedKey = NSSBase64_DecodeBuffer(0, 0, split_key[cur_piece], strlen(split_key[cur_piece])); 507 508 if (wrappedKey == 0) { 509 purple_debug(PURPLE_DEBUG_ERROR, "pidgin-encryption", "(%d) %s", 510 2, _("Error parsing RSANSS key\n")); 511 g_free(key); 512 g_strfreev(split_key); 513 return 0; 514 } 515 516 certPubKeyInfo = SECKEY_DecodeDERSubjectPublicKeyInfo(wrappedKey); 517 518 SECITEM_FreeItem(wrappedKey, PR_TRUE); 519 520 if (certPubKeyInfo == NULL) { 521 purple_debug(PURPLE_DEBUG_ERROR, "pidgin-encryption", "(%d) %s", 522 3, _("Error parsing RSANSS key\n")); 523 g_free(key); 524 g_strfreev(split_key); 525 return 0; 526 } 527 528 key->store.rsa_nss.pub = SECKEY_ExtractPublicKey(certPubKeyInfo); 529 530 if (key->store.rsa_nss.pub == NULL) { 531 purple_debug(PURPLE_DEBUG_ERROR, "pidgin-encryption", "(%d) %s", 532 4, _("Error parsing RSANSS key\n")); 533 g_free(key); 534 g_strfreev(split_key); 535 return 0; 536 } 537 538 SECKEY_DestroySubjectPublicKeyInfo(certPubKeyInfo); 539 540 generate_digest(key->digest, key->store.rsa_nss.pub); 541 generate_fingerprint(key->fingerprint, key->store.rsa_nss.pub); 542 543 g_snprintf(key->length, sizeof(key->length), "%d", 544 8 * SECKEY_PublicKeyStrength(key->store.rsa_nss.pub)); 545 546 if (split_key[++cur_piece] == 0) { 547 /* No private part, so return a public key: */ 548 g_strfreev(split_key); 549 return key; 550 } 551 552 /* ------------------------------------------------------------------------ */ 553 /* Extract Private key: */ 554 /* */ 555 556 iv = NSSBase64_DecodeBuffer(0, 0, split_key[cur_piece], 557 strlen(split_key[cur_piece])); 558 559 if (split_key[++cur_piece] == 0) { 560 /* only part of a private key */ 561 purple_debug(PURPLE_DEBUG_ERROR, "pidgin-encryption", "(%d) %s", 562 5, _("Error parsing RSANSS key\n")); 563 g_free(key); 564 g_strfreev(split_key); 565 /* SECItem_FreeItem will ignore null arguments, so just call it to clean up */ 566 SECITEM_ZfreeItem (iv, PR_TRUE); 567 return 0; 568 } 569 570 wrappedKey = NSSBase64_DecodeBuffer(0, 0, split_key[cur_piece], 571 strlen(split_key[cur_piece])); 572 573 if ((iv == 0) || (wrappedKey == 0)) { 574 purple_debug(PURPLE_DEBUG_ERROR, "pidgin-encryption", "(%d) %s", 575 6, _("Error parsing RSANSS key\n")); 576 g_free(key); 577 g_strfreev(split_key); 578 SECITEM_ZfreeItem (iv, PR_TRUE); 579 SECITEM_ZfreeItem (wrappedKey, PR_TRUE); 580 return 0; 581 } 582 583 pubKeyValue = SECITEM_DupItem(&key->store.rsa_nss.pub->u.rsa.modulus); 584 585 symSlot = PK11_GetBestSlot(SymEncryptionType, NULL); 586 g_assert(symSlot != 0); 587 588 symKeyItem.data = &symKeyData[0]; 589 symKeyItem.len = sizeof(symKeyData); 590 591 symKey = PK11_ImportSymKey(symSlot, PK11_GetKeyGen(SymEncryptionType), 592 PK11_OriginUnwrap, CKA_WRAP, &symKeyItem, NULL); 593 594 if (!symKey) { 595 purple_debug(PURPLE_DEBUG_ERROR, "pidgin-encryption", "(%d) %s", 596 7, _("Error parsing RSANSS key\n")); 597 g_strfreev(split_key); 598 599 SECKEY_DestroyPublicKey(key->store.rsa_nss.pub); 600 SECITEM_ZfreeItem (iv, PR_TRUE); 601 SECITEM_ZfreeItem (pubKeyValue, PR_TRUE); 602 g_free(key); 603 return 0; 604 } 605 606 label.data = NULL; label.len = 0; 607 608 key->store.rsa_nss.priv = 609 PK11_UnwrapPrivKey(symSlot, symKey, SymEncryptionType, iv, 610 wrappedKey, &label, pubKeyValue, 611 PR_FALSE, PR_FALSE, CKK_RSA, attribs, NumAttribs, 0); 612 613 SECITEM_ZfreeItem (iv, PR_TRUE); 614 SECITEM_ZfreeItem (wrappedKey, PR_TRUE); 615 SECITEM_FreeItem (pubKeyValue, PR_TRUE); 616 PK11_FreeSymKey(symKey); 617 618 if (key->store.rsa_nss.priv == 0) { 619 purple_debug(PURPLE_DEBUG_ERROR, "pidgin-encryption", "(%d) %s", 620 8, _("Error parsing RSANSS key\n")); 621 g_strfreev(split_key); 622 623 SECKEY_DestroyPublicKey(key->store.rsa_nss.pub); 624 g_free(key); 625 return 0; 626 } 627 /* should sanity check public/private pair */ 628 629 g_strfreev(split_key); 630 631 return key; 632 } 633 634 635 crypt_key* rsa_nss_make_pub_from_priv(crypt_key* priv_key) { 636 crypt_key* pub_key = g_malloc(sizeof(crypt_key)); 637 638 pub_key->proto = rsa_nss_proto; 639 strcpy(pub_key->length, priv_key->length); 640 strncpy(pub_key->digest, priv_key->digest, KEY_DIGEST_LENGTH); 641 strncpy(pub_key->fingerprint, priv_key->fingerprint, KEY_FINGERPRINT_LENGTH); 642 643 pub_key->store.rsa_nss.pub = copy_public_rsa_key(priv_key->store.rsa_nss.pub); 644 pub_key->store.rsa_nss.priv = 0; 645 646 return pub_key; 647 } 648 649 int rsa_nss_encrypt(unsigned char** encrypted, unsigned char* msg, int msg_len, 650 crypt_key* pub_key){ 651 652 SECKEYPublicKey * key = pub_key->store.rsa_nss.pub; 653 654 int modulus_len = SECKEY_PublicKeyStrength(key); 655 656 int unpadded_block_len = oaep_max_unpadded_len(modulus_len); 657 658 int num_blocks = ((msg_len - 1) / unpadded_block_len) + 1; 659 660 unsigned char* msg_cur, *encrypt_cur; 661 662 int msg_block_len; 663 664 unsigned char *padded_block = g_malloc(modulus_len); 665 666 int ret; 667 SECStatus rv; 668 669 // purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "Starting Encrypt\n"); 670 671 *encrypted = g_malloc(num_blocks * modulus_len); 672 673 msg_cur = msg; 674 encrypt_cur = *encrypted; 675 676 while (msg_cur < msg + msg_len) { 677 678 msg_block_len = unpadded_block_len; 679 if (msg_cur + msg_block_len > msg + msg_len) { 680 msg_block_len = msg + msg_len - msg_cur; 681 } 682 683 ret = oaep_pad_block(padded_block, modulus_len, msg_cur, msg_block_len); 684 if (!ret) { 685 g_free(padded_block); 686 g_free(*encrypted); 687 *encrypted = 0; 688 return 0; 689 } 690 rv = PK11_PubEncryptRaw(key, encrypt_cur, padded_block, 691 modulus_len, 0); 692 if (rv != SECSuccess) { 693 g_free(padded_block); 694 g_free(*encrypted); 695 *encrypted = 0; 696 return 0; 697 } 698 699 msg_cur += msg_block_len; 700 encrypt_cur += modulus_len; 701 } 702 703 g_free(padded_block); 704 // purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "Ending Encrypt\n"); 705 706 return (encrypt_cur - *encrypted); 707 } 708 709 int rsa_nss_decrypt(unsigned char** decrypted, unsigned char* msg, int msg_len, 710 crypt_key* priv_key){ 711 712 SECKEYPrivateKey * key = priv_key->store.rsa_nss.priv; 713 714 int modulus_len = SECKEY_PublicKeyStrength(priv_key->store.rsa_nss.pub); 715 716 int unpadded_block_len = oaep_max_unpadded_len(modulus_len); 717 718 int num_blocks = msg_len / modulus_len; 719 720 unsigned char* msg_cur, *decrypt_cur; 721 722 unsigned int decrypt_block_size; 723 724 unsigned char *padded_block = g_malloc(modulus_len); 725 726 int ret; 727 SECStatus rv; 728 729 purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "Starting Decrypt\n"); 730 731 *decrypted = g_malloc(num_blocks * unpadded_block_len + 1); 732 733 msg_cur = msg; 734 decrypt_cur = *decrypted; 735 736 if (num_blocks * modulus_len != msg_len) { /* not an even number of blocks */ 737 purple_debug(PURPLE_DEBUG_ERROR, "pidgin-encryption", "Not a multiple of block len: %d %d %d\n", 738 num_blocks, modulus_len, msg_len); 739 g_free(padded_block); 740 g_free(*decrypted); 741 *decrypted = 0; 742 return 0; 743 } 744 745 while (msg_cur < msg + msg_len) { 746 747 rv = PK11_PubDecryptRaw(key, padded_block, &decrypt_block_size, modulus_len, 748 msg_cur, modulus_len); 749 750 if (rv != SECSuccess) { 751 purple_debug(PURPLE_DEBUG_ERROR, "pidgin-encryption", "PubDecryptRaw failed %d\n", rv); 752 g_free(padded_block); 753 g_free(*decrypted); 754 *decrypted = 0; 755 return 0; 756 } 757 758 g_assert(decrypt_block_size == modulus_len); /* for now. Don't understand how */ 759 /* this could not be true */ 760 761 ret = oaep_unpad_block(decrypt_cur, &decrypt_block_size, padded_block, modulus_len); 762 if (!ret) { 763 purple_debug(PURPLE_DEBUG_ERROR, "pidgin-encryption", "OAEP unpadding failed\n"); 764 g_free(padded_block); 765 g_free(*decrypted); 766 *decrypted = 0; 767 return 0; 768 } 769 770 msg_cur += modulus_len; 771 decrypt_cur += decrypt_block_size; 772 } 773 774 g_free(padded_block); 775 776 /* Null terminate what just came out, in case someone tries to use it as a string */ 777 *decrypt_cur = 0; 778 779 // purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "Ending Decrypt\n"); 780 return (decrypt_cur - *decrypted); 781 } 782 783 int rsa_nss_sign(unsigned char** signed_msg, unsigned char* msg, int msg_len, 784 crypt_key* priv_key, crypt_key* pub_key) { 785 786 SECKEYPrivateKey * key = priv_key->store.rsa_nss.priv; 787 int modulus_len = SECKEY_PublicKeyStrength(priv_key->store.rsa_nss.pub); 788 unsigned char *sig_pos, *tmp_sig; 789 790 SECStatus rv; 791 unsigned int out_block_size; 792 793 const int salt_len = 20; 794 795 gchar *nonce_str = PE_nonce_to_str(&pub_key->store.rsa_nss.nonce); 796 int nonce_len = strlen(nonce_str); 797 798 PE_incr_nonce(&pub_key->store.rsa_nss.nonce); 799 800 *signed_msg = g_malloc(msg_len + modulus_len + nonce_len + 1); 801 tmp_sig = g_malloc(modulus_len); 802 memcpy(*signed_msg, nonce_str, nonce_len); 803 (*signed_msg)[nonce_len]=':'; 804 805 memcpy(*signed_msg + nonce_len + 1, msg, msg_len); 806 sig_pos = *signed_msg + msg_len + nonce_len + 1 ; 807 808 g_free(nonce_str); 809 810 pss_generate_sig(tmp_sig, modulus_len, *signed_msg, msg_len + nonce_len + 1, salt_len); 811 812 rv = PK11_PubDecryptRaw(key, sig_pos, &out_block_size, modulus_len, 813 tmp_sig, modulus_len); 814 815 if (rv != SECSuccess) { 816 purple_debug(PURPLE_DEBUG_ERROR, "pidgin-encryption", "PK11_PubDecryptRaw Failed\n"); 817 g_free(*signed_msg); 818 g_free(tmp_sig); 819 *signed_msg = 0; 820 return 0; 821 } 822 823 g_assert(out_block_size == modulus_len); /* dunno why they yield out_block_size */ 824 825 g_free(tmp_sig); 826 827 return msg_len + nonce_len + 1 + modulus_len; 828 } 829 830 // Returns length of authed string, or 0 if not authenticated 831 // g_malloc's space for the authed string, and null terminates the result 832 // If returning zero, may return a message ID (nonce) as the authed string 833 834 int rsa_nss_auth(unsigned char** authed, unsigned char* msg, int msg_len, 835 crypt_key* pub_key, const char* name) { 836 837 SECKEYPublicKey * key = pub_key->store.rsa_nss.pub; 838 int modulus_len = SECKEY_PublicKeyStrength(key); 839 unsigned char *tmp_sig; 840 841 SECStatus rv; 842 int verified; 843 844 gchar *nonce_msg, **nonce_msg_split; 845 846 purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "Starting Auth\n"); 847 848 *authed = 0; 849 850 if (msg_len < modulus_len) { 851 purple_debug(PURPLE_DEBUG_ERROR, "pidgin-encryption", "Bad msg_len in Auth\n"); 852 return 0; 853 } 854 855 tmp_sig = g_malloc(modulus_len); 856 857 rv = PK11_PubEncryptRaw(key, tmp_sig, msg + msg_len - modulus_len, 858 modulus_len, 0); 859 860 if (rv != SECSuccess) { 861 purple_debug(PURPLE_DEBUG_ERROR, "pidgin-encryption", "PK11_PubEncryptRaw Failed\n"); 862 g_free(tmp_sig); 863 return 0; 864 } 865 866 /* purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "Auth 2\n"); */ 867 868 verified = pss_check_sig(tmp_sig, modulus_len, msg, msg_len - modulus_len); 869 870 g_free(tmp_sig); 871 872 if (!verified) { 873 purple_debug(PURPLE_DEBUG_ERROR, "pidgin-encryption", _("Bad signature on message (len %d, mod %d)\n"), 874 msg_len, modulus_len); 875 return 0; 876 } 877 878 /* purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "Auth 3\n"); */ 879 880 nonce_msg = g_strndup((char*)msg, msg_len - modulus_len); 881 nonce_msg_split = g_strsplit(nonce_msg, ":", 2); 882 g_free(nonce_msg); 883 884 /* purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "Auth 4\n"); */ 885 886 if ((nonce_msg_split[0] == 0) || (nonce_msg_split[1] == 0)) { 887 purple_debug(PURPLE_DEBUG_ERROR, "pidgin-encryption", "No Nonce in message\n"); 888 g_strfreev(nonce_msg_split); 889 return 0; 890 } 891 892 /* purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "Auth 5\n"); */ 893 894 if (!PE_check_incoming_nonce(name, nonce_msg_split[0])) { 895 purple_debug(PURPLE_DEBUG_ERROR, "pidgin-encryption", "Bad Nonce in message\n"); 896 /* a hack: return the nonce that was sent, to send to other side, to cause */ 897 /* message to be re-sent */ 898 *authed = (unsigned char*) g_strdup(nonce_msg_split[0]); 899 900 g_strfreev(nonce_msg_split); 901 return 0; 902 } 903 904 /* purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "Auth 6\n"); */ 905 906 *authed = (unsigned char*)nonce_msg_split[1]; 907 g_free(nonce_msg_split[0]); 908 g_free(nonce_msg_split); 909 910 purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "Auth End\n"); 911 912 return strlen((char*)*authed); 913 } 914 915 int rsa_nss_calc_unencrypted_size(struct crypt_key* key, int insize) { 916 int modulus_len = SECKEY_PublicKeyStrength(key->store.rsa_nss.pub); 917 int unpadded_block_len = oaep_max_unpadded_len(modulus_len); 918 919 int num_blocks = insize / modulus_len; /* floor: max number of blocks that could fit */ 920 921 return num_blocks * unpadded_block_len; 922 } 923 924 int rsa_nss_calc_unsigned_size(struct crypt_key* key, int insize) { 925 int modulus_len, nonce_len; 926 927 purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "calc_unsigned_size\n"); 928 929 modulus_len = SECKEY_PublicKeyStrength(key->store.rsa_nss.pub); 930 nonce_len = PE_nonce_str_len(); 931 932 purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "modulus_len:%d:%d\n", modulus_len, nonce_len); 933 934 if (insize < modulus_len + nonce_len) return 0; 935 return insize - modulus_len - nonce_len - 1; /* -1 from ":" after nonce */ 936 } 937 938 939