diff options
| author | Simeon Simeonov | 2018-03-06 10:46:02 +0100 |
|---|---|---|
| committer | Simeon Simeonov | 2018-03-06 10:46:02 +0100 |
| commit | 8c56039d67bd910a334b2ddd009c6df4bb01cc8b (patch) | |
| tree | d46d42e6e46a3be8fce101cee7fab70747dda462 | |
| parent | dd8e01ae9524d8109ce66b9294c64f50159d9672 (diff) | |
Add the core master-password functionality in libsylph/ssl.[c,h]
| -rw-r--r-- | libsylph/ssl.c | 96 | ||||
| -rw-r--r-- | libsylph/ssl.h | 24 |
2 files changed, 111 insertions, 9 deletions
diff --git a/libsylph/ssl.c b/libsylph/ssl.c index 82b77b4..21686e1 100644 --- a/libsylph/ssl.c +++ b/libsylph/ssl.c | |||
| @@ -36,6 +36,8 @@ | |||
| 36 | #define CIPHER EVP_aes_256_cfb() | 36 | #define CIPHER EVP_aes_256_cfb() |
| 37 | #define KEY_HASH EVP_sha256() | 37 | #define KEY_HASH EVP_sha256() |
| 38 | #define DIGEST_HASH EVP_sha256() | 38 | #define DIGEST_HASH EVP_sha256() |
| 39 | #define PBKDF2_DIGEST_SIZE 64 | ||
| 40 | #define PBKDF2_ITERATIONS 100000 | ||
| 39 | 41 | ||
| 40 | static SSL_CTX *ssl_ctx_SSLv23 = NULL; | 42 | static SSL_CTX *ssl_ctx_SSLv23 = NULL; |
| 41 | static SSL_CTX *ssl_ctx_TLSv1 = NULL; | 43 | static SSL_CTX *ssl_ctx_TLSv1 = NULL; |
| @@ -779,4 +781,98 @@ cleanup: | |||
| 779 | 781 | ||
| 780 | } | 782 | } |
| 781 | 783 | ||
| 784 | gint generate_password_hash(gchar **password_hash, | ||
| 785 | const gchar *password, | ||
| 786 | const guchar *salt) { | ||
| 787 | /* | ||
| 788 | * Hashes 'password' using PKCS5_PBKDF2_HMAC with SHA512 and 'salt', | ||
| 789 | * and assigns a string to 'password_hash' with the following format: | ||
| 790 | * pbkdf2_sha512$iterations$base64(salt)$base64(password_hash) | ||
| 791 | */ | ||
| 792 | guchar lsalt[SALT_SIZE]; | ||
| 793 | gchar *PBKDF2_digest, *salt_b64, *digest_b64; | ||
| 794 | |||
| 795 | if (salt == NULL) { | ||
| 796 | if (RAND_bytes(lsalt, SALT_SIZE) != 1) { | ||
| 797 | g_fprintf(stderr, "Random problems...\n"); | ||
| 798 | return RC_ERROR; | ||
| 799 | } | ||
| 800 | } else { | ||
| 801 | memcpy(lsalt, salt, SALT_SIZE); | ||
| 802 | } | ||
| 803 | |||
| 804 | PBKDF2_digest = OPENSSL_malloc(PBKDF2_DIGEST_SIZE); | ||
| 805 | OPENSSL_cleanse(PBKDF2_digest, PBKDF2_DIGEST_SIZE); | ||
| 806 | |||
| 807 | PKCS5_PBKDF2_HMAC(password, | ||
| 808 | strlen(password), | ||
| 809 | lsalt, | ||
| 810 | SALT_SIZE, | ||
| 811 | PBKDF2_ITERATIONS, | ||
| 812 | EVP_sha512(), | ||
| 813 | PBKDF2_DIGEST_SIZE, | ||
| 814 | (guchar *) PBKDF2_digest); | ||
| 815 | digest_b64 = g_base64_encode((guchar *) PBKDF2_digest, PBKDF2_DIGEST_SIZE); | ||
| 816 | OPENSSL_cleanse(PBKDF2_digest, PBKDF2_DIGEST_SIZE); | ||
| 817 | OPENSSL_free(PBKDF2_digest); | ||
| 818 | |||
| 819 | salt_b64 = g_base64_encode(lsalt, SALT_SIZE); | ||
| 820 | |||
| 821 | *password_hash = g_strdup_printf("pbkdf2_sha512$%d$%s$%s", | ||
| 822 | PBKDF2_ITERATIONS, | ||
| 823 | salt_b64, | ||
| 824 | digest_b64); | ||
| 825 | |||
| 826 | OPENSSL_cleanse(digest_b64, strlen(digest_b64)); | ||
| 827 | OPENSSL_free(digest_b64); | ||
| 828 | |||
| 829 | OPENSSL_cleanse(salt_b64, strlen(salt_b64)); | ||
| 830 | OPENSSL_free(salt_b64); | ||
| 831 | |||
| 832 | return RC_OK; | ||
| 833 | |||
| 834 | } | ||
| 835 | |||
| 836 | gint check_password(const gchar *password, const gchar *password_hash) { | ||
| 837 | |||
| 838 | gint token_counter, rc; | ||
| 839 | guchar *salt; | ||
| 840 | gchar **tokens, *new_hash; | ||
| 841 | gsize salt_length; | ||
| 842 | |||
| 843 | rc = RC_ERROR; | ||
| 844 | tokens = g_strsplit(password_hash, | ||
| 845 | "$", | ||
| 846 | -1); | ||
| 847 | token_counter = 0; | ||
| 848 | while (*(tokens + token_counter) != NULL) { | ||
| 849 | ++token_counter; | ||
| 850 | } | ||
| 851 | |||
| 852 | if (token_counter != 4) { | ||
| 853 | g_fprintf(stderr, "Invalid password hash...\n"); | ||
| 854 | goto cleanup; | ||
| 855 | } | ||
| 856 | |||
| 857 | salt = g_base64_decode(*(tokens + 2), &salt_length); | ||
| 858 | if (salt_length != SALT_SIZE) { | ||
| 859 | g_fprintf(stderr, "Salt size does not match\n"); | ||
| 860 | goto cleanup; | ||
| 861 | } | ||
| 862 | |||
| 863 | if (generate_password_hash(&new_hash, password, salt) != RC_OK) { | ||
| 864 | g_fprintf(stderr, "Password hash generation failed\n"); | ||
| 865 | goto cleanup; | ||
| 866 | } | ||
| 867 | |||
| 868 | rc = g_strcmp0(password_hash, new_hash); | ||
| 869 | |||
| 870 | cleanup: | ||
| 871 | g_free(salt); | ||
| 872 | g_free(new_hash); | ||
| 873 | g_strfreev(tokens); | ||
| 874 | return rc; | ||
| 875 | |||
| 876 | } | ||
| 877 | |||
| 782 | #endif /* USE_SSL */ | 878 | #endif /* USE_SSL */ |
diff --git a/libsylph/ssl.h b/libsylph/ssl.h index 94ab4b7..6338911 100644 --- a/libsylph/ssl.h +++ b/libsylph/ssl.h | |||
| @@ -68,17 +68,23 @@ void ssl_set_verify_func (SSLVerifyFunc func); | |||
| 68 | 68 | ||
| 69 | /* master password related code */ | 69 | /* master password related code */ |
| 70 | gint encrypt_data(gchar **encrypted, | 70 | gint encrypt_data(gchar **encrypted, |
| 71 | gint *length_encrypted, | 71 | gint *length_encrypted, |
| 72 | const gchar *data, | 72 | const gchar *data, |
| 73 | const gchar *passphrase, | 73 | const gchar *passphrase, |
| 74 | gint length_data, | 74 | gint length_data, |
| 75 | guint min_data_length, | 75 | guint min_data_length, |
| 76 | gboolean rnd_salt); | 76 | gboolean rnd_salt); |
| 77 | 77 | ||
| 78 | gint decrypt_data(gchar **decrypted, | 78 | gint decrypt_data(gchar **decrypted, |
| 79 | const gchar *data, | 79 | const gchar *data, |
| 80 | const gchar *passphrase, | 80 | const gchar *passphrase, |
| 81 | gint length_data); | 81 | gint length_data); |
| 82 | |||
| 83 | gint generate_password_hash(gchar **password_hash, | ||
| 84 | const gchar *password, | ||
| 85 | const guchar *salt); | ||
| 86 | |||
| 87 | gint check_password(const gchar *password, const gchar *password_hash); | ||
| 82 | /* ---------------------------- */ | 88 | /* ---------------------------- */ |
| 83 | #endif /* USE_SSL */ | 89 | #endif /* USE_SSL */ |
| 84 | 90 | ||
