summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimeon Simeonov2018-03-09 14:02:34 +0100
committerSimeon Simeonov2018-03-09 14:02:34 +0100
commitf1babd48f5259186cd1233288992f942d4b5b0bb (patch)
tree54d740ef2201fceb3e54fac31272e80e65079ec7
parent57944f6147f077ccf4d84b9d2659f4e8645e8858 (diff)
Complete rewrite of the master password implementation
-rw-r--r--libsylph/account.c24
-rw-r--r--libsylph/imap.c16
-rw-r--r--libsylph/masterpassword.c159
-rw-r--r--libsylph/masterpassword.h6
-rw-r--r--libsylph/news.c7
-rw-r--r--libsylph/pop.c11
-rw-r--r--libsylph/prefs_account.c1
-rw-r--r--libsylph/prefs_account.h2
-rw-r--r--libsylph/ssl.c712
-rw-r--r--src/main.c28
-rw-r--r--src/send_message.c22
11 files changed, 529 insertions, 459 deletions
diff --git a/libsylph/account.c b/libsylph/account.c
index 7440434..2431bf3 100644
--- a/libsylph/account.c
+++ b/libsylph/account.c
@@ -36,9 +36,6 @@
36#include "procheader.h" 36#include "procheader.h"
37#include "utils.h" 37#include "utils.h"
38#include "sylmain.h" 38#include "sylmain.h"
39#include "prefs_common.h"
40#include "masterpassword.h"
41
42 39
43PrefsAccount *cur_account; 40PrefsAccount *cur_account;
44 41
@@ -54,24 +51,6 @@ void account_read_config_all(void)
54 FILE *fp; 51 FILE *fp;
55 gchar buf[PREFSBUFSIZE]; 52 gchar buf[PREFSBUFSIZE];
56 PrefsAccount *ac_prefs; 53 PrefsAccount *ac_prefs;
57#if USE_SSL
58 if (prefs_common.use_master_password) {
59 if (prefs_common.master_password_hash != NULL) {
60 /* allow 3 attempts to enter the master password */
61 if (check_master_password_interactively(3) != 0) {
62 /* master password does not match the hash */
63 g_free(master_password);
64 master_password = NULL;
65 }
66 } else {
67 /* No master password set (no master_password_hash) */
68 set_master_password_interactively(3);
69 }
70 /* TODO: Warning if password is NULL */
71 } else {
72 master_password = NULL;
73 }
74#endif
75 54
76 debug_print(_("Reading all config for each account...\n")); 55 debug_print(_("Reading all config for each account...\n"));
77 56
@@ -100,9 +79,6 @@ void account_read_config_all(void)
100 for (cur = ac_label_list; cur != NULL; cur = cur->next) { 79 for (cur = ac_label_list; cur != NULL; cur = cur->next) {
101 ac_prefs = prefs_account_new(); 80 ac_prefs = prefs_account_new();
102 prefs_account_read_config(ac_prefs, (gchar *)cur->data); 81 prefs_account_read_config(ac_prefs, (gchar *)cur->data);
103#if USE_SSL
104 ac_prefs->master_password = master_password;
105#endif
106 account_list = g_list_append(account_list, ac_prefs); 82 account_list = g_list_append(account_list, ac_prefs);
107 if (ac_prefs->is_default) 83 if (ac_prefs->is_default)
108 cur_account = ac_prefs; 84 cur_account = ac_prefs;
diff --git a/libsylph/imap.c b/libsylph/imap.c
index 0cd4409..9ee4b15 100644
--- a/libsylph/imap.c
+++ b/libsylph/imap.c
@@ -52,6 +52,7 @@
52#include "utils.h" 52#include "utils.h"
53#include "prefs_common.h" 53#include "prefs_common.h"
54#include "virtual.h" 54#include "virtual.h"
55#include "masterpassword.h"
55 56
56#define IMAP4_PORT 143 57#define IMAP4_PORT 143
57#if USE_SSL 58#if USE_SSL
@@ -705,19 +706,9 @@ static gint imap_session_connect(IMAPSession *session)
705 account = (PrefsAccount *)(SESSION(session)->data); 706 account = (PrefsAccount *)(SESSION(session)->data);
706 707
707 log_message(_("creating IMAP4 connection to %s:%d ...\n"), 708 log_message(_("creating IMAP4 connection to %s:%d ...\n"),
708 SESSION(session)->server, SESSION(session)->port); 709 SESSION(session)->server, SESSION(session)->port);
709 710
710 if (prefs_common.use_master_password && account->master_password != NULL) { 711 pass = decrypt_with_master_password(account->passwd);
711 if (decrypt_data(&pass,
712 account->passwd,
713 account->master_password,
714 strlen(account->passwd) + 1) != RC_OK) {
715 session_destroy(session);
716 return -1;
717 }
718 } else {
719 pass = account->passwd;
720 }
721 if (!pass) 712 if (!pass)
722 pass = account->tmp_pass; 713 pass = account->tmp_pass;
723 if (!pass) { 714 if (!pass) {
@@ -731,6 +722,7 @@ static gint imap_session_connect(IMAPSession *session)
731 account->tmp_pass = tmp_pass; 722 account->tmp_pass = tmp_pass;
732 pass = account->tmp_pass; 723 pass = account->tmp_pass;
733 } 724 }
725
734 if (account->use_socks && account->use_socks_for_recv && 726 if (account->use_socks && account->use_socks_for_recv &&
735 account->proxy_host) { 727 account->proxy_host) {
736 socks_info = socks_info_new(account->socks_type, account->proxy_host, account->proxy_port, account->use_proxy_auth ? account->proxy_name : NULL, account->use_proxy_auth ? account->proxy_pass : NULL); 728 socks_info = socks_info_new(account->socks_type, account->proxy_host, account->proxy_port, account->use_proxy_auth ? account->proxy_name : NULL, account->use_proxy_auth ? account->proxy_pass : NULL);
diff --git a/libsylph/masterpassword.c b/libsylph/masterpassword.c
index ee443aa..4cef644 100644
--- a/libsylph/masterpassword.c
+++ b/libsylph/masterpassword.c
@@ -21,6 +21,8 @@
21#include "config.h" 21#include "config.h"
22#endif 22#endif
23 23
24#include <glib/gi18n.h>
25
24#include "prefs_common.h" 26#include "prefs_common.h"
25#include "ssl.h" 27#include "ssl.h"
26#include "utils.h" 28#include "utils.h"
@@ -29,72 +31,141 @@
29gchar *master_password; 31gchar *master_password;
30 32
31void set_master_password(const char *password) { 33void set_master_password(const char *password) {
32 master_password = password; 34 master_password = password;
33} 35}
34 36
35gchar *get_master_password(void) { 37gchar *get_master_password(void) {
36 return master_password; 38 return master_password;
37} 39}
38 40
41void unload_master_password(void) {
42
39#if USE_SSL 43#if USE_SSL
44 OPENSSL_cleanse(master_password, strlen(master_password));
45#endif
46 g_free(master_password);
47 master_password = NULL;
40 48
41gint set_master_password_interactively(guint max_attempts) { 49}
50
51gboolean master_password_active(void) {
52
53#if USE_SSL
54 return ((master_password != NULL) &&
55 prefs_common.use_master_password);
56#else
57 return FALSE;
58#endif
59
60}
42 61
43 if (master_password != NULL) 62gchar *decrypt_with_master_password(gchar *str) {
44 return 0; /* master_password already set */
45 63
46 master_password = input_set_new_password(max_attempts); 64#if USE_SSL
65 gchar *new_str;
47 66
48 if (master_password == NULL) 67 if ((!str) || (!master_password_active()))
49 return 1; 68 return str; /* do nothing */
50 69
51 if (generate_password_hash( 70 if (decrypt_data(&new_str,
52 &prefs_common.master_password_hash, 71 str,
53 master_password, 72 master_password,
54 NULL) != RC_OK) { 73 strlen(str)) != RC_OK) {
55 /* should not really happen unless buggy code / library */ 74 OPENSSL_cleanse(new_str, strlen(new_str));
56 g_free(prefs_common.master_password_hash); 75 g_free(new_str);
57 prefs_common.master_password_hash = NULL; 76 return str;
58 debug_print(_("Could not generate master password hash")); 77 }
59 return 1;
60 }
61 78
62 prefs_common_write_config(); 79 return new_str;
63 return 0; 80#else
81 return str; /* do nothing */
82#endif
64 83
65} 84}
66 85
67gint check_master_password_interactively(guint max_attempts) { 86gchar *encrypt_with_master_password(gchar *str) {
87
88#if USE_SSL
89 gchar *new_str;
90 gint length_encrypted;
68 91
69 guint cnt; 92 if ((!str) || (!master_password_active()))
93 return str; /* do nothing */
70 94
71 if (max_attempts < 1) 95 if (encrypt_data(&new_str,
72 return 1; 96 &length_encrypted,
97 str,
98 master_password,
99 strlen(str),
100 32, /* TODO: to be set in prefs_common */
101 TRUE) != RC_OK) {
102 OPENSSL_cleanse(new_str, strlen(new_str));
103 g_free(new_str);
104 return str;
105 }
73 106
74 if (prefs_common.master_password_hash != NULL) { 107 return new_str;
75 return 1; 108#else
76 } 109 return str; /* do nothing */
110#endif
111
112}
113
114#if USE_SSL
115gint set_master_password_interactively(guint max_attempts) {
77 116
78 if (master_password != NULL) { 117 if (master_password == NULL)
79 /* password already cached */ 118 master_password = input_set_new_password(max_attempts);
80 return check_password(master_password,
81 prefs_common.master_password_hash);
82 }
83 119
84 for (cnt = 0; cnt < max_attempts; ++cnt) { 120 if (master_password == NULL)
85 master_password = input_query_master_password(); 121 return 1;
86 if (check_password(master_password,
87 prefs_common.master_password_hash) == RC_OK) {
88 return RC_OK; /* match */
89 }
90 debug_print(_("Wrong master password entered (%d)\n"), cnt);
91 /* TODO: clear before free? */
92 g_free(master_password);
93 master_password = NULL;
94 }
95 122
96 return 1; /* no match */ 123 if (generate_password_hash(
124 &prefs_common.master_password_hash,
125 master_password,
126 NULL) != RC_OK) {
127 /* should not really happen unless buggy code / library */
128 g_free(prefs_common.master_password_hash);
129 prefs_common.master_password_hash = NULL;
130 debug_print(_("Could not generate master password hash"));
131 return 1;
132 }
133
134 prefs_common_write_config();
135 return 0;
97 136
98} 137}
99 138
139gint check_master_password_interactively(guint max_attempts) {
140
141 guint cnt;
142
143 if (max_attempts < 1)
144 return 1;
145
146 if (prefs_common.master_password_hash != NULL) {
147 return 1;
148 }
149
150 if (master_password != NULL) {
151 /* password already cached */
152 return check_password(master_password,
153 prefs_common.master_password_hash);
154 }
155
156 for (cnt = 0; cnt < max_attempts; ++cnt) {
157 master_password = input_query_master_password();
158 if (check_password(master_password,
159 prefs_common.master_password_hash) == RC_OK) {
160 return RC_OK; /* match */
161 }
162 debug_print(_("Wrong master password entered (%d)\n"), cnt);
163 OPENSSL_cleanse(master_password, strlen(master_password));
164 g_free(master_password);
165 master_password = NULL;
166 }
167
168 return 1; /* no match */
169
170}
100#endif /* USE_SSL */ 171#endif /* USE_SSL */
diff --git a/libsylph/masterpassword.h b/libsylph/masterpassword.h
index b2798ce..9d00384 100644
--- a/libsylph/masterpassword.h
+++ b/libsylph/masterpassword.h
@@ -27,12 +27,14 @@
27extern gchar *master_password; 27extern gchar *master_password;
28void set_master_password(const char *password); 28void set_master_password(const char *password);
29gchar *get_master_password(void); 29gchar *get_master_password(void);
30void unload_master_password(void);
31gboolean master_password_active(void);
32gchar *decrypt_with_master_password(gchar *str);
33gchar *encrypt_with_master_password(gchar *str);
30 34
31#if USE_SSL 35#if USE_SSL
32
33gint set_master_password_interactively(guint max_attempts); 36gint set_master_password_interactively(guint max_attempts);
34gint check_master_password_interactively(guint max_attempts); 37gint check_master_password_interactively(guint max_attempts);
35
36#endif /* USE_SSL */ 38#endif /* USE_SSL */
37 39
38#endif /* __MASTERPASSWORD_H__ */ 40#endif /* __MASTERPASSWORD_H__ */
diff --git a/libsylph/news.c b/libsylph/news.c
index ffff9f9..b7a922a 100644
--- a/libsylph/news.c
+++ b/libsylph/news.c
@@ -44,6 +44,7 @@
44#include "utils.h" 44#include "utils.h"
45#include "prefs_common.h" 45#include "prefs_common.h"
46#include "prefs_account.h" 46#include "prefs_account.h"
47#include "masterpassword.h"
47#if USE_SSL 48#if USE_SSL
48# include "ssl.h" 49# include "ssl.h"
49#endif 50#endif
@@ -250,7 +251,11 @@ static Session *news_session_new_for_folder(Folder *folder)
250 if (ac->use_nntp_auth && ac->userid && ac->userid[0]) { 251 if (ac->use_nntp_auth && ac->userid && ac->userid[0]) {
251 userid = ac->userid; 252 userid = ac->userid;
252 if (ac->passwd && ac->passwd[0]) 253 if (ac->passwd && ac->passwd[0])
253 passwd = g_strdup(ac->passwd); 254 if (master_password_active()) {
255 passwd = decrypt_with_master_password(ac->passwd);
256 } else {
257 passwd = g_strdup(ac->passwd);
258 }
254 else 259 else
255 passwd = input_query_password(ac->nntp_server, userid); 260 passwd = input_query_password(ac->nntp_server, userid);
256 } 261 }
diff --git a/libsylph/pop.c b/libsylph/pop.c
index 8cb7f5c..a387f5e 100644
--- a/libsylph/pop.c
+++ b/libsylph/pop.c
@@ -39,6 +39,7 @@
39#include "prefs_account.h" 39#include "prefs_account.h"
40#include "utils.h" 40#include "utils.h"
41#include "recv.h" 41#include "recv.h"
42#include "masterpassword.h"
42 43
43gint pop3_greeting_recv (Pop3Session *session, 44gint pop3_greeting_recv (Pop3Session *session,
44 const gchar *msg); 45 const gchar *msg);
@@ -437,8 +438,14 @@ Session *pop3_session_new(PrefsAccount *account)
437 session->error_msg = NULL; 438 session->error_msg = NULL;
438 439
439 session->user = g_strdup(account->userid); 440 session->user = g_strdup(account->userid);
440 session->pass = account->passwd ? g_strdup(account->passwd) : 441 if (master_password_active()) {
441 account->tmp_pass ? g_strdup(account->tmp_pass) : NULL; 442 session->pass = account->passwd ? decrypt_with_master_password(
443 account->passwd) : account->tmp_pass ? g_strdup(
444 account->tmp_pass) : NULL;
445 } else {
446 session->pass = account->passwd ? g_strdup(account->passwd) :
447 account->tmp_pass ? g_strdup(account->tmp_pass) : NULL;
448 }
442 449
443 SESSION(session)->server = g_strdup(account->recv_server); 450 SESSION(session)->server = g_strdup(account->recv_server);
444 451
diff --git a/libsylph/prefs_account.c b/libsylph/prefs_account.c
index 07605fb..1aecba9 100644
--- a/libsylph/prefs_account.c
+++ b/libsylph/prefs_account.c
@@ -218,7 +218,6 @@ void prefs_account_read_config(PrefsAccount *ac_prefs, const gchar *label)
218 g_free(rcpath); 218 g_free(rcpath);
219 219
220 *ac_prefs = tmp_ac_prefs; 220 *ac_prefs = tmp_ac_prefs;
221 ac_prefs->master_password = NULL;
222 while (*p && !g_ascii_isdigit(*p)) p++; 221 while (*p && !g_ascii_isdigit(*p)) p++;
223 id = atoi(p); 222 id = atoi(p);
224 if (id < 0) g_warning("wrong account id: %d\n", id); 223 if (id < 0) g_warning("wrong account id: %d\n", id);
diff --git a/libsylph/prefs_account.h b/libsylph/prefs_account.h
index 68badd8..ad899f8 100644
--- a/libsylph/prefs_account.h
+++ b/libsylph/prefs_account.h
@@ -187,8 +187,6 @@ struct _PrefsAccount
187 /* Compose */ 187 /* Compose */
188 gchar *sig_names[10]; 188 gchar *sig_names[10];
189 gchar *sig_texts[10]; 189 gchar *sig_texts[10];
190
191 gchar *master_password;
192}; 190};
193 191
194PrefsAccount *prefs_account_new (void); 192PrefsAccount *prefs_account_new (void);
diff --git a/libsylph/ssl.c b/libsylph/ssl.c
index 5042f74..44b2935 100644
--- a/libsylph/ssl.c
+++ b/libsylph/ssl.c
@@ -411,467 +411,465 @@ void ssl_set_verify_func(SSLVerifyFunc func)
411 411
412/* master password related functions */ 412/* master password related functions */
413static gint secure_derive_key(guchar *key, 413static gint secure_derive_key(guchar *key,
414 gint length_key, 414 gint length_key,
415 const gchar *passphrase, 415 const gchar *passphrase,
416 const guchar *salt) { 416 const guchar *salt) {
417 417
418 guint length_buffer, length_hash; 418 guint length_buffer, length_hash;
419 guchar *buffer, *ptr_hash; 419 guchar *buffer, *ptr_hash;
420 420
421 EVP_MD_CTX *mdctx; 421 EVP_MD_CTX *mdctx;
422 422
423 OPENSSL_cleanse(key, length_key); 423 OPENSSL_cleanse(key, length_key);
424 424
425 length_buffer = SALT_SIZE + strlen(passphrase); 425 length_buffer = SALT_SIZE + strlen(passphrase);
426 buffer = OPENSSL_malloc(length_buffer); 426 buffer = OPENSSL_malloc(length_buffer);
427 OPENSSL_cleanse(buffer, length_buffer); 427 OPENSSL_cleanse(buffer, length_buffer);
428 428
429 memcpy(buffer, salt, SALT_SIZE); 429 memcpy(buffer, salt, SALT_SIZE);
430 memcpy(buffer + SALT_SIZE, passphrase, strlen(passphrase)); 430 memcpy(buffer + SALT_SIZE, passphrase, strlen(passphrase));
431 431
432 mdctx = EVP_MD_CTX_create(); 432 mdctx = EVP_MD_CTX_create();
433 EVP_DigestInit_ex(mdctx, KEY_HASH, NULL); 433 EVP_DigestInit_ex(mdctx, KEY_HASH, NULL);
434 EVP_DigestUpdate(mdctx, buffer, length_buffer); 434 EVP_DigestUpdate(mdctx, buffer, length_buffer);
435 OPENSSL_cleanse(buffer, length_buffer); 435 OPENSSL_cleanse(buffer, length_buffer);
436 436
437 ptr_hash = OPENSSL_malloc(EVP_MD_size(KEY_HASH)); 437 ptr_hash = OPENSSL_malloc(EVP_MD_size(KEY_HASH));
438 EVP_DigestFinal_ex(mdctx, ptr_hash, &length_hash); 438 EVP_DigestFinal_ex(mdctx, ptr_hash, &length_hash);
439 439
440 memcpy(key, 440 memcpy(key,
441 ptr_hash, 441 ptr_hash,
442 (length_hash > length_key) ? length_key : length_hash); 442 (length_hash > length_key) ? length_key : length_hash);
443 443
444 OPENSSL_cleanse(ptr_hash, length_hash); 444 OPENSSL_cleanse(ptr_hash, length_hash);
445 OPENSSL_free(ptr_hash); 445 OPENSSL_free(ptr_hash);
446 OPENSSL_free(buffer); 446 OPENSSL_free(buffer);
447 EVP_MD_CTX_destroy(mdctx); 447 EVP_MD_CTX_destroy(mdctx);
448 448
449 return RC_OK; 449 return RC_OK;
450 450
451} 451}
452 452
453
454gint encrypt_data(gchar **encrypted, 453gint encrypt_data(gchar **encrypted,
455 gint *length_encrypted, 454 gint *length_encrypted,
456 const gchar *data, 455 const gchar *data,
457 const gchar *passphrase, 456 const gchar *passphrase,
458 gint length_data, 457 gint length_data,
459 guint min_data_length, 458 guint min_data_length,
460 gboolean rnd_salt) { 459 gboolean rnd_salt) {
461 460
462 gint crypt_buffer_cnt, rc; 461 gint crypt_buffer_cnt, rc;
463 guint key_size, length_hash; 462 guint key_size, length_hash;
464 guint length_cleartext, length_ciphertext, length_total; 463 guint length_cleartext, length_ciphertext, length_total;
465 guchar salt[SALT_SIZE]; 464 guchar salt[SALT_SIZE];
466 guchar *ciphertext_buffer, *total_buffer; 465 guchar *ciphertext_buffer, *total_buffer;
467 /* sensitive buffers and counters */ 466 /* sensitive buffers and counters */
468 guint length_data_payload, length_padding; 467 guint length_data_payload, length_padding;
469 gchar str_data_size[3]; 468 gchar str_data_size[3];
470 guchar *data_payload_buffer, *hash_buffer, *padding_buffer, *key; 469 guchar *data_payload_buffer, *hash_buffer, *padding_buffer, *key;
471 guchar *cleartext_buffer; 470 guchar *cleartext_buffer;
472 471
473 EVP_CIPHER_CTX *ctx; 472 EVP_CIPHER_CTX *ctx;
474 EVP_MD_CTX *mdctx; 473 EVP_MD_CTX *mdctx;
475 474
476 rc = RC_ERROR; 475 rc = RC_ERROR;
477 476
478 if (length_data < 1) { 477 if (length_data < 1) {
479 return -1; 478 return -1;
480 } 479 }
481 if (rnd_salt) { 480 if (rnd_salt) {
482 if (RAND_bytes(salt, SALT_SIZE) != 1) { 481 if (RAND_bytes(salt, SALT_SIZE) != 1) {
483 debug_print("Random problems...\n"); 482 debug_print("Random problems...\n");
484 goto cleanup; 483 goto cleanup;
485 } 484 }
486 } else { 485 } else {
487 strncpy((gchar *)salt, "FOR TESTING ONLY", SALT_SIZE); 486 strncpy((gchar *)salt, "FOR TESTING ONLY", SALT_SIZE);
488 } 487 }
489 488
490 key_size = EVP_CIPHER_key_length(CIPHER); 489 key_size = EVP_CIPHER_key_length(CIPHER);
491 key = OPENSSL_malloc(key_size); 490 key = OPENSSL_malloc(key_size);
492 OPENSSL_cleanse(key, key_size); 491 OPENSSL_cleanse(key, key_size);
493 if (secure_derive_key(key, 492 if (secure_derive_key(key,
494 key_size, 493 key_size,
495 passphrase, 494 passphrase,
496 salt) != RC_OK) { 495 salt) != RC_OK) {
497 OPENSSL_cleanse(key, key_size); 496 OPENSSL_cleanse(key, key_size);
498 debug_print("Could not generate secure key\n"); 497 debug_print("Could not generate secure key\n");
499 goto cleanup; 498 goto cleanup;
500 } 499 }
501 500
502 /* prepare the data-buffer */ 501 /* prepare the data-buffer */
503 length_padding = 0; 502 length_padding = 0;
504 if (length_data < min_data_length) { 503 if (length_data < min_data_length) {
505 g_snprintf(str_data_size, 3, "%02d", length_data); 504 g_snprintf(str_data_size, 3, "%02d", length_data);
506 length_padding = min_data_length - length_data; 505 length_padding = min_data_length - length_data;
507 padding_buffer = OPENSSL_malloc(length_padding); 506 padding_buffer = OPENSSL_malloc(length_padding);
508 OPENSSL_cleanse(padding_buffer, length_padding); 507 OPENSSL_cleanse(padding_buffer, length_padding);
509 if (RAND_bytes(padding_buffer, length_padding) != 1) { 508 if (RAND_bytes(padding_buffer, length_padding) != 1) {
510 debug_print("Random problems...\n"); 509 debug_print("Random problems...\n");
511 goto cleanup; 510 goto cleanup;
512 } 511 }
513 } else { 512 } else {
514 g_snprintf(str_data_size, 3, "-1"); 513 g_snprintf(str_data_size, 3, "-1");
515 } 514 }
516 515
517 length_data_payload = 2 + length_data + length_padding; 516 length_data_payload = 2 + length_data + length_padding;
518 data_payload_buffer = OPENSSL_malloc(length_data_payload); 517 data_payload_buffer = OPENSSL_malloc(length_data_payload);
519 OPENSSL_cleanse(data_payload_buffer, length_data_payload); 518 OPENSSL_cleanse(data_payload_buffer, length_data_payload);
520 519
521 memcpy(data_payload_buffer, str_data_size, 2); 520 memcpy(data_payload_buffer, str_data_size, 2);
522 memcpy(data_payload_buffer + 2, data, length_data); 521 memcpy(data_payload_buffer + 2, data, length_data);
523 if (length_padding > 0) { 522 if (length_padding > 0) {
524 memcpy(data_payload_buffer + (2 + length_data), 523 memcpy(data_payload_buffer + (2 + length_data),
525 padding_buffer, 524 padding_buffer,
526 length_padding); 525 length_padding);
527 } 526 }
528 527
529 mdctx = EVP_MD_CTX_create(); 528 mdctx = EVP_MD_CTX_create();
530 EVP_DigestInit_ex(mdctx, DIGEST_HASH, NULL); 529 EVP_DigestInit_ex(mdctx, DIGEST_HASH, NULL);
531 EVP_DigestUpdate(mdctx, data_payload_buffer, length_data_payload); 530 EVP_DigestUpdate(mdctx, data_payload_buffer, length_data_payload);
532 531
533 length_hash = EVP_MD_size(DIGEST_HASH); 532 length_hash = EVP_MD_size(DIGEST_HASH);
534 hash_buffer = OPENSSL_malloc(length_hash); 533 hash_buffer = OPENSSL_malloc(length_hash);
535 OPENSSL_cleanse(hash_buffer, length_hash); 534 OPENSSL_cleanse(hash_buffer, length_hash);
536 EVP_DigestFinal_ex(mdctx, hash_buffer, NULL); 535 EVP_DigestFinal_ex(mdctx, hash_buffer, NULL);
537 536
538 length_cleartext = length_hash + length_data_payload; 537 length_cleartext = length_hash + length_data_payload;
539 538
540 cleartext_buffer = OPENSSL_malloc(length_cleartext); 539 cleartext_buffer = OPENSSL_malloc(length_cleartext);
541 OPENSSL_cleanse(cleartext_buffer, length_cleartext); 540 OPENSSL_cleanse(cleartext_buffer, length_cleartext);
542 541
543 /* assemble cleartext-buffer */ 542 /* assemble cleartext-buffer */
544 memcpy(cleartext_buffer, hash_buffer, length_hash); 543 memcpy(cleartext_buffer, hash_buffer, length_hash);
545 memcpy(cleartext_buffer + length_hash, 544 memcpy(cleartext_buffer + length_hash,
546 data_payload_buffer, 545 data_payload_buffer,
547 length_data_payload); 546 length_data_payload);
548 OPENSSL_cleanse(data_payload_buffer, length_data_payload); /* sensitive */ 547 OPENSSL_cleanse(data_payload_buffer, length_data_payload); /* sensitive */
549 548
550 /* encryption */ 549 /* encryption */
551 if (!(ctx = EVP_CIPHER_CTX_new())) { 550 if (!(ctx = EVP_CIPHER_CTX_new())) {
552 debug_print("New ctx failed\n"); 551 debug_print("New ctx failed\n");
553 goto cleanup; 552 goto cleanup;
554 } 553 }
555 554
556 length_ciphertext = 0; 555 length_ciphertext = 0;
557 if (EVP_EncryptInit_ex(ctx, CIPHER, NULL, key, salt) != 1) { 556 if (EVP_EncryptInit_ex(ctx, CIPHER, NULL, key, salt) != 1) {
558 debug_print("EVP_EncryptInit_ex failed\n"); 557 debug_print("EVP_EncryptInit_ex failed\n");
559 goto cleanup; 558 goto cleanup;
560 } 559 }
561 560
562 ciphertext_buffer = OPENSSL_malloc(length_cleartext); 561 ciphertext_buffer = OPENSSL_malloc(length_cleartext);
563 562
564 crypt_buffer_cnt = 0; 563 crypt_buffer_cnt = 0;
565 while(1) { 564 while(1) {
566 if (EVP_EncryptUpdate(ctx, 565 if (EVP_EncryptUpdate(ctx,
567 ciphertext_buffer + length_ciphertext, 566 ciphertext_buffer + length_ciphertext,
568 &crypt_buffer_cnt, 567 &crypt_buffer_cnt,
569 cleartext_buffer + length_ciphertext, 568 cleartext_buffer + length_ciphertext,
570 1) != 1) { /* one byte at a time */ 569 1) != 1) { /* one byte at a time */
571 debug_print("EVP_EncryptUpdate failed\n"); 570 debug_print("EVP_EncryptUpdate failed\n");
572 goto cleanup; 571 goto cleanup;
573 } 572 }
574 573
575 if (crypt_buffer_cnt != 1) { /* paranoia */ 574 if (crypt_buffer_cnt != 1) { /* paranoia */
576 debug_print("The sizes of enc and dec text do not correspond\n"); 575 debug_print("The sizes of enc and dec text do not correspond\n");
577 goto cleanup; 576 goto cleanup;
578 } 577 }
579 578
580 ++length_ciphertext; 579 ++length_ciphertext;
581 580
582 if (length_ciphertext >= length_cleartext) { 581 if (length_ciphertext >= length_cleartext) {
583 break; 582 break;
584 } 583 }
585 } 584 }
586 /* No padding required for the CFB mode */ 585 /* No padding required for the CFB mode */
587 586
588 OPENSSL_cleanse(cleartext_buffer, length_cleartext); /* sensitive */ 587 OPENSSL_cleanse(cleartext_buffer, length_cleartext); /* sensitive */
589 length_total = SALT_SIZE + length_ciphertext; 588 length_total = SALT_SIZE + length_ciphertext;
590 total_buffer = OPENSSL_malloc(length_total); 589 total_buffer = OPENSSL_malloc(length_total);
591 590
592 memcpy(total_buffer, salt, SALT_SIZE); 591 memcpy(total_buffer, salt, SALT_SIZE);
593 memcpy(total_buffer + SALT_SIZE, ciphertext_buffer, length_ciphertext); 592 memcpy(total_buffer + SALT_SIZE, ciphertext_buffer, length_ciphertext);
594 593
595 *encrypted = g_base64_encode(total_buffer, length_total); 594 *encrypted = g_base64_encode(total_buffer, length_total);
596 *length_encrypted = strlen(*encrypted); 595 *length_encrypted = strlen(*encrypted);
597 596
598 rc = RC_OK; 597 rc = RC_OK;
599 598
600cleanup: 599cleanup:
601 /* key */ 600 /* key */
602 OPENSSL_cleanse(key, key_size); 601 OPENSSL_cleanse(key, key_size);
603 OPENSSL_free(key); 602 OPENSSL_free(key);
604 /* cleartext buffer */ 603 /* cleartext buffer */
605 OPENSSL_cleanse(cleartext_buffer, length_cleartext); 604 OPENSSL_cleanse(cleartext_buffer, length_cleartext);
606 OPENSSL_free(cleartext_buffer); 605 OPENSSL_free(cleartext_buffer);
607 /* payload buffer */ 606 /* payload buffer */
608 OPENSSL_cleanse(data_payload_buffer, length_data_payload); 607 OPENSSL_cleanse(data_payload_buffer, length_data_payload);
609 OPENSSL_free(data_payload_buffer); 608 OPENSSL_free(data_payload_buffer);
610 /* hash */ 609 /* hash */
611 OPENSSL_cleanse(hash_buffer, length_hash); 610 OPENSSL_cleanse(hash_buffer, length_hash);
612 OPENSSL_free(hash_buffer); 611 OPENSSL_free(hash_buffer);
613 /* padding */ 612 /* padding */
614 if (length_padding > 0) { 613 if (length_padding > 0) {
615 OPENSSL_cleanse(padding_buffer, length_padding); 614 OPENSSL_cleanse(padding_buffer, length_padding);
616 OPENSSL_free(padding_buffer); 615 OPENSSL_free(padding_buffer);
617 } 616 }
618 617
619 OPENSSL_cleanse(str_data_size, 3); /* paranoia */ 618 OPENSSL_cleanse(str_data_size, 3); /* paranoia */
620 619
621 /* ciphertext buffer */ 620 /* ciphertext buffer */
622 OPENSSL_free(ciphertext_buffer); 621 OPENSSL_free(ciphertext_buffer);
623 622
624 /* total buffer */ 623 /* total buffer */
625 OPENSSL_free(total_buffer); 624 OPENSSL_free(total_buffer);
626 625
627 length_data_payload = 0; 626 length_data_payload = 0;
628 length_padding = 0; 627 length_padding = 0;
629 628
630 EVP_CIPHER_CTX_free(ctx); 629 EVP_CIPHER_CTX_free(ctx);
631 EVP_MD_CTX_destroy(mdctx); 630 EVP_MD_CTX_destroy(mdctx);
632 631
633 return rc; 632 return rc;
634 633
635} 634}
636 635
637
638gint decrypt_data(gchar **decrypted, 636gint decrypt_data(gchar **decrypted,
639 const gchar *data, 637 const gchar *data,
640 const gchar *passphrase, 638 const gchar *passphrase,
641 gint length_data) { 639 gint length_data) {
642 640
643 gint rc; /* return code */ 641 gint rc; /* return code */
644 gint decrypt_buffer_cnt, length_ciphertext, length_decrypted; 642 gint decrypt_buffer_cnt, length_ciphertext, length_decrypted;
645 guint key_size, length_hash, length_cleartext; 643 guint key_size, length_hash, length_cleartext;
646 gsize length_total; 644 gsize length_total;
647 guchar salt[SALT_SIZE]; 645 guchar salt[SALT_SIZE];
648 guchar *ciphertext_buffer, *total_buffer; 646 guchar *ciphertext_buffer, *total_buffer;
649 /* sensitive buffers and counters */ 647 /* sensitive buffers and counters */
650 gint data_size; 648 gint data_size;
651 guint length_data_payload; 649 guint length_data_payload;
652 gchar str_data_size[3]; 650 gchar str_data_size[3];
653 guchar *data_payload_buffer, *hash_buffer, *key; 651 guchar *data_payload_buffer, *hash_buffer, *key;
654 guchar *cleartext_buffer; 652 guchar *cleartext_buffer;
655 653
656 EVP_CIPHER_CTX *ctx; 654 EVP_CIPHER_CTX *ctx;
657 EVP_MD_CTX *mdctx; 655 EVP_MD_CTX *mdctx;
658 656
659 rc = -1; 657 rc = -1;
660 658
661 if (length_data < 1) { 659 if (length_data < 1) {
662 return -1; 660 return -1;
663 } 661 }
664 662
665 total_buffer = g_base64_decode(data, &length_total); 663 total_buffer = g_base64_decode(data, &length_total);
666 length_ciphertext = length_total - SALT_SIZE; 664 length_ciphertext = length_total - SALT_SIZE;
667 ciphertext_buffer = OPENSSL_malloc(length_ciphertext); 665 ciphertext_buffer = OPENSSL_malloc(length_ciphertext);
668 OPENSSL_cleanse(ciphertext_buffer, length_ciphertext); 666 OPENSSL_cleanse(ciphertext_buffer, length_ciphertext);
669 667
670 memcpy(salt, total_buffer, SALT_SIZE); 668 memcpy(salt, total_buffer, SALT_SIZE);
671 memcpy(ciphertext_buffer, total_buffer + SALT_SIZE, length_ciphertext); 669 memcpy(ciphertext_buffer, total_buffer + SALT_SIZE, length_ciphertext);
672 670
673 key_size = EVP_CIPHER_key_length(CIPHER); 671 key_size = EVP_CIPHER_key_length(CIPHER);
674 672
675 /* decryption */ 673 /* decryption */
676 if(!(ctx = EVP_CIPHER_CTX_new())) { 674 if(!(ctx = EVP_CIPHER_CTX_new())) {
677 debug_print("New ctx failed\n"); 675 debug_print("New ctx failed\n");
678 goto cleanup; 676 goto cleanup;
679 } 677 }
680 678
681 key = OPENSSL_malloc(key_size); 679 key = OPENSSL_malloc(key_size);
682 OPENSSL_cleanse(key, key_size); 680 OPENSSL_cleanse(key, key_size);
683 if (secure_derive_key(key, 681 if (secure_derive_key(key,
684 key_size, 682 key_size,
685 passphrase, 683 passphrase,
686 salt) != 0) { 684 salt) != 0) {
687 OPENSSL_cleanse(key, key_size); 685 OPENSSL_cleanse(key, key_size);
688 debug_print("Could not generate secure key\n"); 686 debug_print("Could not generate secure key\n");
689 goto cleanup; 687 goto cleanup;
690 } 688 }
691 689
692 if (EVP_DecryptInit_ex(ctx, CIPHER, NULL, key, salt) != 1) { 690 if (EVP_DecryptInit_ex(ctx, CIPHER, NULL, key, salt) != 1) {
693 debug_print("EVP_DecryptInit_ex failed\n"); 691 debug_print("EVP_DecryptInit_ex failed\n");
694 goto cleanup; 692 goto cleanup;
695 } 693 }
696 OPENSSL_cleanse(key, key_size); /* highly sensitive */ 694 OPENSSL_cleanse(key, key_size); /* highly sensitive */
697 cleartext_buffer = OPENSSL_malloc(length_ciphertext); 695 cleartext_buffer = OPENSSL_malloc(length_ciphertext);
698 OPENSSL_cleanse(cleartext_buffer, length_ciphertext); 696 OPENSSL_cleanse(cleartext_buffer, length_ciphertext);
699 697
700 length_cleartext = 0; 698 length_cleartext = 0;
701 decrypt_buffer_cnt = 0; 699 decrypt_buffer_cnt = 0;
702 700
703 while(1) { 701 while(1) {
704 if (EVP_DecryptUpdate(ctx, 702 if (EVP_DecryptUpdate(ctx,
705 cleartext_buffer + length_cleartext, 703 cleartext_buffer + length_cleartext,
706 &decrypt_buffer_cnt, 704 &decrypt_buffer_cnt,
707 ciphertext_buffer + length_cleartext, 705 ciphertext_buffer + length_cleartext,
708 1) != 1) { /* one byte at a time */ 706 1) != 1) { /* one byte at a time */
709 debug_print("EVP_EncryptUpdate failed\n"); 707 debug_print("EVP_EncryptUpdate failed\n");
710 goto cleanup; 708 goto cleanup;
711 } 709 }
712 710
713 if (decrypt_buffer_cnt != 1) { /* paranoia */ 711 if (decrypt_buffer_cnt != 1) { /* paranoia */
714 debug_print("The sizes of enc and dec text do not correspond"); 712 debug_print("The sizes of enc and dec text do not correspond");
715 goto cleanup; 713 goto cleanup;
716 } 714 }
717 715
718 ++length_cleartext; 716 ++length_cleartext;
719 717
720 if (length_cleartext >= length_ciphertext) { 718 if (length_cleartext >= length_ciphertext) {
721 break; 719 break;
722 } 720 }
723 } 721 }
724 722
725 723
726 length_hash = EVP_MD_size(DIGEST_HASH); 724 length_hash = EVP_MD_size(DIGEST_HASH);
727 hash_buffer = OPENSSL_malloc(length_hash); 725 hash_buffer = OPENSSL_malloc(length_hash);
728 length_data_payload = length_cleartext - length_hash; 726 length_data_payload = length_cleartext - length_hash;
729 data_payload_buffer = OPENSSL_malloc(length_data_payload); 727 data_payload_buffer = OPENSSL_malloc(length_data_payload);
730 OPENSSL_cleanse(data_payload_buffer, length_data_payload); 728 OPENSSL_cleanse(data_payload_buffer, length_data_payload);
731 729
732 memcpy(data_payload_buffer, 730 memcpy(data_payload_buffer,
733 cleartext_buffer + length_hash, 731 cleartext_buffer + length_hash,
734 length_data_payload); 732 length_data_payload);
735 733
736 mdctx = EVP_MD_CTX_create(); 734 mdctx = EVP_MD_CTX_create();
737 EVP_DigestInit_ex(mdctx, DIGEST_HASH, NULL); 735 EVP_DigestInit_ex(mdctx, DIGEST_HASH, NULL);
738 EVP_DigestUpdate(mdctx, data_payload_buffer, length_data_payload); 736 EVP_DigestUpdate(mdctx, data_payload_buffer, length_data_payload);
739 EVP_DigestFinal_ex(mdctx, hash_buffer, &length_hash); 737 EVP_DigestFinal_ex(mdctx, hash_buffer, &length_hash);
740 738
741 if (strncmp((const gchar*) hash_buffer, 739 if (strncmp((const gchar*) hash_buffer,
742 (const gchar*) cleartext_buffer, 740 (const gchar*) cleartext_buffer,
743 length_hash) != 0) { 741 length_hash) != 0) {
744 debug_print("Invalid hash\n"); 742 debug_print("Invalid hash\n");
745 rc = RC_WRONG_HASH_OR_KEY; 743 rc = RC_WRONG_HASH_OR_KEY;
746 goto cleanup; 744 goto cleanup;
747 } 745 }
748 746
749 memcpy(str_data_size, cleartext_buffer + length_hash, 2); 747 memcpy(str_data_size, cleartext_buffer + length_hash, 2);
750 data_size = atoi(str_data_size); 748 data_size = atoi(str_data_size);
751 749
752 if (data_size < 0) { 750 if (data_size < 0) {
753 length_decrypted = length_data_payload - 2; 751 length_decrypted = length_data_payload - 2;
754 } else { 752 } else {
755 length_decrypted = data_size; 753 length_decrypted = data_size;
756 } 754 }
757 *decrypted = OPENSSL_malloc(length_decrypted); 755 *decrypted = OPENSSL_malloc(length_decrypted);
758 memcpy(*decrypted, data_payload_buffer + 2, length_decrypted); 756 memcpy(*decrypted, data_payload_buffer + 2, length_decrypted);
759 757
760 rc = RC_OK; 758 rc = RC_OK;
761 759
762cleanup: 760cleanup:
763 761
764 /* key */ 762 /* key */
765 OPENSSL_cleanse(key, key_size); 763 OPENSSL_cleanse(key, key_size);
766 OPENSSL_free(key); 764 OPENSSL_free(key);
767 /* payload buffer */ 765 /* payload buffer */
768 OPENSSL_cleanse(data_payload_buffer, length_data_payload); 766 OPENSSL_cleanse(data_payload_buffer, length_data_payload);
769 OPENSSL_free(data_payload_buffer); 767 OPENSSL_free(data_payload_buffer);
770 /* hash */ 768 /* hash */
771 OPENSSL_cleanse(hash_buffer, length_hash); 769 OPENSSL_cleanse(hash_buffer, length_hash);
772 OPENSSL_free(hash_buffer); 770 OPENSSL_free(hash_buffer);
773 /* ciphertext */ 771 /* ciphertext */
774 OPENSSL_free(ciphertext_buffer); 772 OPENSSL_free(ciphertext_buffer);
775 OPENSSL_free(total_buffer); 773 OPENSSL_free(total_buffer);
776 774
777 EVP_CIPHER_CTX_free(ctx); 775 EVP_CIPHER_CTX_free(ctx);
778 EVP_MD_CTX_destroy(mdctx); 776 EVP_MD_CTX_destroy(mdctx);
779 777
780 return rc; 778 return rc;
781 779
782} 780}
783 781
784gint generate_password_hash(gchar **password_hash, 782gint generate_password_hash(gchar **password_hash,
785 const gchar *password, 783 const gchar *password,
786 const guchar *salt) { 784 const guchar *salt) {
787 /* 785 /*
788 * Hashes 'password' using PKCS5_PBKDF2_HMAC with SHA512 and 'salt', 786 * Hashes 'password' using PKCS5_PBKDF2_HMAC with SHA512 and 'salt',
789 * and assigns a string to 'password_hash' with the following format: 787 * and assigns a string to 'password_hash' with the following format:
790 * pbkdf2_sha512$iterations$base64(salt)$base64(password_hash) 788 * pbkdf2_sha512$iterations$base64(salt)$base64(password_hash)
791 */ 789 */
792 guchar lsalt[SALT_SIZE]; 790 guchar lsalt[SALT_SIZE];
793 gchar *PBKDF2_digest, *salt_b64, *digest_b64; 791 gchar *PBKDF2_digest, *salt_b64, *digest_b64;
794 792
795 if (salt == NULL) { 793 if (salt == NULL) {
796 if (RAND_bytes(lsalt, SALT_SIZE) != 1) { 794 if (RAND_bytes(lsalt, SALT_SIZE) != 1) {
797 debug_print("Random problems...\n"); 795 debug_print("Random problems...\n");
798 return RC_ERROR; 796 return RC_ERROR;
799 } 797 }
800 } else { 798 } else {
801 memcpy(lsalt, salt, SALT_SIZE); 799 memcpy(lsalt, salt, SALT_SIZE);
802 } 800 }
803 801
804 PBKDF2_digest = OPENSSL_malloc(PBKDF2_DIGEST_SIZE); 802 PBKDF2_digest = OPENSSL_malloc(PBKDF2_DIGEST_SIZE);
805 OPENSSL_cleanse(PBKDF2_digest, PBKDF2_DIGEST_SIZE); 803 OPENSSL_cleanse(PBKDF2_digest, PBKDF2_DIGEST_SIZE);
806 804
807 PKCS5_PBKDF2_HMAC(password, 805 PKCS5_PBKDF2_HMAC(password,
808 strlen(password), 806 strlen(password),
809 lsalt, 807 lsalt,
810 SALT_SIZE, 808 SALT_SIZE,
811 PBKDF2_ITERATIONS, 809 PBKDF2_ITERATIONS,
812 EVP_sha512(), 810 EVP_sha512(),
813 PBKDF2_DIGEST_SIZE, 811 PBKDF2_DIGEST_SIZE,
814 (guchar *) PBKDF2_digest); 812 (guchar *) PBKDF2_digest);
815 digest_b64 = g_base64_encode((guchar *) PBKDF2_digest, PBKDF2_DIGEST_SIZE); 813 digest_b64 = g_base64_encode((guchar *) PBKDF2_digest, PBKDF2_DIGEST_SIZE);
816 OPENSSL_cleanse(PBKDF2_digest, PBKDF2_DIGEST_SIZE); 814 OPENSSL_cleanse(PBKDF2_digest, PBKDF2_DIGEST_SIZE);
817 OPENSSL_free(PBKDF2_digest); 815 OPENSSL_free(PBKDF2_digest);
818 816
819 salt_b64 = g_base64_encode(lsalt, SALT_SIZE); 817 salt_b64 = g_base64_encode(lsalt, SALT_SIZE);
820 818
821 *password_hash = g_strdup_printf("pbkdf2_sha512$%d$%s$%s", 819 *password_hash = g_strdup_printf("pbkdf2_sha512$%d$%s$%s",
822 PBKDF2_ITERATIONS, 820 PBKDF2_ITERATIONS,
823 salt_b64, 821 salt_b64,
824 digest_b64); 822 digest_b64);
825 823
826 OPENSSL_cleanse(digest_b64, strlen(digest_b64)); 824 OPENSSL_cleanse(digest_b64, strlen(digest_b64));
827 OPENSSL_free(digest_b64); 825 OPENSSL_free(digest_b64);
828 826
829 OPENSSL_cleanse(salt_b64, strlen(salt_b64)); 827 OPENSSL_cleanse(salt_b64, strlen(salt_b64));
830 OPENSSL_free(salt_b64); 828 OPENSSL_free(salt_b64);
831 829
832 return RC_OK; 830 return RC_OK;
833 831
834} 832}
835 833
836gint check_password(const gchar *password, const gchar *password_hash) { 834gint check_password(const gchar *password, const gchar *password_hash) {
837 835
838 gint token_counter, rc; 836 gint token_counter, rc;
839 guchar *salt; 837 guchar *salt;
840 gchar **tokens, *new_hash; 838 gchar **tokens, *new_hash;
841 gsize salt_length; 839 gsize salt_length;
842 840
843 rc = RC_ERROR; 841 rc = RC_ERROR;
844 tokens = g_strsplit(password_hash, 842 tokens = g_strsplit(password_hash,
845 "$", 843 "$",
846 -1); 844 -1);
847 token_counter = 0; 845 token_counter = 0;
848 while (*(tokens + token_counter) != NULL) { 846 while (*(tokens + token_counter) != NULL) {
849 ++token_counter; 847 ++token_counter;
850 } 848 }
851 849
852 if (token_counter != 4) { 850 if (token_counter != 4) {
853 debug_print("Invalid password hash...\n"); 851 debug_print("Invalid password hash...\n");
854 goto cleanup; 852 goto cleanup;
855 } 853 }
856 854
857 salt = g_base64_decode(*(tokens + 2), &salt_length); 855 salt = g_base64_decode(*(tokens + 2), &salt_length);
858 if (salt_length != SALT_SIZE) { 856 if (salt_length != SALT_SIZE) {
859 debug_print("Salt size does not match\n"); 857 debug_print("Salt size does not match\n");
860 goto cleanup; 858 goto cleanup;
861 } 859 }
862 860
863 if (generate_password_hash(&new_hash, password, salt) != RC_OK) { 861 if (generate_password_hash(&new_hash, password, salt) != RC_OK) {
864 debug_print("Password hash generation failed\n"); 862 debug_print("Password hash generation failed\n");
865 goto cleanup; 863 goto cleanup;
866 } 864 }
867 865
868 rc = g_strcmp0(password_hash, new_hash); 866 rc = g_strcmp0(password_hash, new_hash);
869 867
870cleanup: 868cleanup:
871 g_free(salt); 869 g_free(salt);
872 g_free(new_hash); 870 g_free(new_hash);
873 g_strfreev(tokens); 871 g_strfreev(tokens);
874 return rc; 872 return rc;
875 873
876} 874}
877 875
diff --git a/src/main.c b/src/main.c
index be8ea54..7c1cd7b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -87,6 +87,7 @@
87#include "foldersel.h" 87#include "foldersel.h"
88#include "update_check.h" 88#include "update_check.h"
89#include "colorlabel.h" 89#include "colorlabel.h"
90#include "masterpassword.h"
90 91
91#if USE_GPGME 92#if USE_GPGME
92# include "rfc2015.h" 93# include "rfc2015.h"
@@ -275,6 +276,32 @@ int main(int argc, char *argv[])
275 CHDIR_EXIT_IF_FAIL(get_home_dir(), 1); 276 CHDIR_EXIT_IF_FAIL(get_home_dir(), 1);
276 277
277 prefs_common_read_config(); 278 prefs_common_read_config();
279 set_master_password(NULL);
280#if USE_SSL
281 if (prefs_common.use_master_password) {
282 if (prefs_common.master_password_hash != NULL) {
283 if (check_master_password_interactively(3)) {
284 if (alertpanel(_("Master password"),
285 _("Unable to set master password"),
286 GTK_STOCK_DISCARD,
287 GTK_STOCK_QUIT,
288 NULL) != G_ALERTDEFAULT) {
289 exit(1);
290 }
291 }
292 } else {
293 if (set_master_password_interactively(3) != 0) {
294 if (alertpanel(_("Master password"),
295 _("Unable to set master password"),
296 GTK_STOCK_DISCARD,
297 GTK_STOCK_QUIT,
298 NULL) != G_ALERTDEFAULT) {
299 exit(1);
300 }
301 }
302 }
303 }
304#endif
278 filter_set_addressbook_func(addressbook_has_address); 305 filter_set_addressbook_func(addressbook_has_address);
279 filter_read_config(); 306 filter_read_config();
280 prefs_actions_read_config(); 307 prefs_actions_read_config();
@@ -995,6 +1022,7 @@ void app_will_exit(gboolean force)
995 1022
996 /* remove temporary files, close log file, socket cleanup */ 1023 /* remove temporary files, close log file, socket cleanup */
997#if USE_SSL 1024#if USE_SSL
1025 unload_master_password();
998 ssl_done(); 1026 ssl_done();
999#endif 1027#endif
1000 syl_cleanup(); 1028 syl_cleanup();
diff --git a/src/send_message.c b/src/send_message.c
index 7b66423..d5fc6e8 100644
--- a/src/send_message.c
+++ b/src/send_message.c
@@ -58,6 +58,7 @@
58#include "inc.h" 58#include "inc.h"
59#include "mainwindow.h" 59#include "mainwindow.h"
60#include "summaryview.h" 60#include "summaryview.h"
61#include "masterpassword.h"
61 62
62#define SMTP_PORT 25 63#define SMTP_PORT 25
63#if USE_SSL 64#if USE_SSL
@@ -648,24 +649,17 @@ static gint send_message_smtp(PrefsAccount *ac_prefs, GSList *to_list, FILE *fp)
648 649
649 if (ac_prefs->smtp_userid) { 650 if (ac_prefs->smtp_userid) {
650 smtp_session->user = g_strdup(ac_prefs->smtp_userid); 651 smtp_session->user = g_strdup(ac_prefs->smtp_userid);
651 if (ac_prefs->smtp_passwd) { 652 if (ac_prefs->smtp_passwd)
652 if(prefs_common.use_master_password && 653 if (master_password_active()) {
653 ac_prefs->master_password != NULL) { 654 smtp_session->pass = decrypt_with_master_password(
654 if (decrypt_data(&(smtp_session->pass), 655 ac_prefs->smtp_passwd);
655 ac_prefs->smtp_passwd,
656 ac_prefs->master_password,
657 strlen(ac_prefs->smtp_passwd) + 1) != RC_OK) {
658 session_destroy(session);
659 return -1;
660 }
661 } else { 656 } else {
662 smtp_session->pass = 657 smtp_session->pass = g_strdup(ac_prefs->smtp_passwd);
663 g_strdup(ac_prefs->smtp_passwd);
664 } 658 }
665 } else if (ac_prefs->tmp_smtp_pass) { 659 else if (ac_prefs->tmp_smtp_pass)
666 smtp_session->pass = 660 smtp_session->pass =
667 g_strdup(ac_prefs->tmp_smtp_pass); 661 g_strdup(ac_prefs->tmp_smtp_pass);
668 } else { 662 else {
669 smtp_session->pass = 663 smtp_session->pass =
670 input_query_password 664 input_query_password
671 (ac_prefs->smtp_server, 665 (ac_prefs->smtp_server,