[epiphany/wip/ephy-sync: 36/86] Implement Fetching Sync Keys act



commit a6046c8eb78f2d6c376128dd9cd2b07ac0917e0f
Author: Gabriel Ivascu <ivascu gabriel59 gmail com>
Date:   Fri Jul 8 17:51:49 2016 +0300

    Implement Fetching Sync Keys act

 src/ephy-sync-crypto.c  |  444 ++++++++++++++++++++++++++++++++++++++---------
 src/ephy-sync-crypto.h  |   91 ++++++----
 src/ephy-sync-secret.c  |    6 +-
 src/ephy-sync-secret.h  |    4 +-
 src/ephy-sync-service.c |  347 ++++++++++++++++++++-----------------
 src/ephy-sync-service.h |   11 +-
 src/ephy-sync-utils.c   |   35 +++--
 src/ephy-sync-utils.h   |   10 +-
 src/prefs-dialog.c      |   17 ++-
 9 files changed, 652 insertions(+), 313 deletions(-)
---
diff --git a/src/ephy-sync-crypto.c b/src/ephy-sync-crypto.c
index 64e560d..01e9b27 100644
--- a/src/ephy-sync-crypto.c
+++ b/src/ephy-sync-crypto.c
@@ -17,6 +17,7 @@
  */
 
 #include "ephy-sync-crypto.h"
+#include "ephy-sync-utils.h"
 
 #include <libsoup/soup.h>
 #include <nettle/hmac.h>
@@ -26,17 +27,31 @@
 
 #define HAWK_VERSION  1
 
-static EphySyncCryptoHawkHeader *
-ephy_sync_crypto_hawk_header_new (gchar                       *header,
-                                  EphySyncCryptoHawkArtifacts *artifacts)
+EphySyncCryptoHawkOptions *
+ephy_sync_crypto_hawk_options_new (gchar *app,
+                                   gchar *dlg,
+                                   gchar *ext,
+                                   gchar *content_type,
+                                   gchar *hash,
+                                   gchar *local_time_offset,
+                                   gchar *nonce,
+                                   gchar *payload,
+                                   gchar *timestamp)
 {
-  EphySyncCryptoHawkHeader *hawk_header;
+  EphySyncCryptoHawkOptions *hawk_options;
 
-  hawk_header = g_slice_new (EphySyncCryptoHawkHeader);
-  hawk_header->header = header;
-  hawk_header->artifacts = artifacts;
+  hawk_options = g_slice_new (EphySyncCryptoHawkOptions);
+  hawk_options->app = app;
+  hawk_options->dlg = dlg;
+  hawk_options->ext = ext;
+  hawk_options->content_type = content_type;
+  hawk_options->hash = hash;
+  hawk_options->local_time_offset = local_time_offset;
+  hawk_options->nonce = nonce;
+  hawk_options->payload = payload;
+  hawk_options->timestamp = timestamp;
 
-  return hawk_header;
+  return hawk_options;
 }
 
 static EphySyncCryptoHawkArtifacts *
@@ -68,9 +83,89 @@ ephy_sync_crypto_hawk_artifacts_new (gchar *app,
   return hawk_artifacts;
 }
 
+static EphySyncCryptoHawkHeader *
+ephy_sync_crypto_hawk_header_new (gchar                       *header,
+                                  EphySyncCryptoHawkArtifacts *artifacts)
+{
+  EphySyncCryptoHawkHeader *hawk_header;
+
+  hawk_header = g_slice_new (EphySyncCryptoHawkHeader);
+  hawk_header->header = header;
+  hawk_header->artifacts = artifacts;
+
+  return hawk_header;
+}
+
+static EphySyncCryptoStretchedCredentials *
+ephy_sync_crypto_stretched_credentials_new (guint8 *quickStretchedPW,
+                                            guint8 *authPW,
+                                            guint8 *unwrapBKey)
+{
+  EphySyncCryptoStretchedCredentials *stretched_credentials;
+
+  stretched_credentials = g_slice_new (EphySyncCryptoStretchedCredentials);
+  stretched_credentials->quickStretchedPW = quickStretchedPW;
+  stretched_credentials->authPW = authPW;
+  stretched_credentials->unwrapBKey = unwrapBKey;
+
+  return stretched_credentials;
+}
+
+static EphySyncCryptoProcessedKFT *
+ephy_sync_crypto_processed_kft_new (guint8 *tokenID,
+                                    guint8 *reqHMACkey,
+                                    guint8 *respHMACkey,
+                                    guint8 *respXORkey)
+{
+  EphySyncCryptoProcessedKFT *processed_kft;
+
+  processed_kft = g_slice_new (EphySyncCryptoProcessedKFT);
+  processed_kft->tokenID = tokenID;
+  processed_kft->reqHMACkey = reqHMACkey;
+  processed_kft->respHMACkey = respHMACkey;
+  processed_kft->respXORkey = respXORkey;
+
+  return processed_kft;
+}
+
+static EphySyncCryptoSyncKeys *
+ephy_sync_crypto_sync_keys_new (guint8 *kA,
+                                guint8 *kB,
+                                guint8 *wrapKB)
+{
+  EphySyncCryptoSyncKeys *sync_keys;
+
+  sync_keys = g_slice_new (EphySyncCryptoSyncKeys);
+  sync_keys->kA = kA;
+  sync_keys->kB = kB;
+  sync_keys->wrapKB = wrapKB;
+
+  return sync_keys;
+}
+
+void
+ephy_sync_crypto_hawk_options_free (EphySyncCryptoHawkOptions *hawk_options)
+{
+  g_return_if_fail (hawk_options != NULL);
+
+  g_free (hawk_options->app);
+  g_free (hawk_options->dlg);
+  g_free (hawk_options->ext);
+  g_free (hawk_options->content_type);
+  g_free (hawk_options->hash);
+  g_free (hawk_options->local_time_offset);
+  g_free (hawk_options->nonce);
+  g_free (hawk_options->payload);
+  g_free (hawk_options->timestamp);
+
+  g_slice_free (EphySyncCryptoHawkOptions, hawk_options);
+}
+
 static void
 ephy_sync_crypto_hawk_artifacts_free (EphySyncCryptoHawkArtifacts *hawk_artifacts)
 {
+  g_return_if_fail (hawk_artifacts != NULL);
+
   g_free (hawk_artifacts->app);
   g_free (hawk_artifacts->dlg);
   g_free (hawk_artifacts->ext);
@@ -85,6 +180,104 @@ ephy_sync_crypto_hawk_artifacts_free (EphySyncCryptoHawkArtifacts *hawk_artifact
   g_slice_free (EphySyncCryptoHawkArtifacts, hawk_artifacts);
 }
 
+void
+ephy_sync_crypto_hawk_header_free (EphySyncCryptoHawkHeader *hawk_header)
+{
+  g_return_if_fail (hawk_header != NULL);
+
+  g_free (hawk_header->header);
+  ephy_sync_crypto_hawk_artifacts_free (hawk_header->artifacts);
+
+  g_slice_free (EphySyncCryptoHawkHeader, hawk_header);
+}
+
+void
+ephy_sync_crypto_stretched_credentials_free (EphySyncCryptoStretchedCredentials *stretched_credentials)
+{
+  g_return_if_fail (stretched_credentials != NULL);
+
+  g_free (stretched_credentials->quickStretchedPW);
+  g_free (stretched_credentials->authPW);
+  g_free (stretched_credentials->unwrapBKey);
+
+  g_slice_free (EphySyncCryptoStretchedCredentials, stretched_credentials);
+}
+
+void
+ephy_sync_crypto_processed_kft_free (EphySyncCryptoProcessedKFT *processed_kft)
+{
+  g_return_if_fail (processed_kft != NULL);
+
+  g_free (processed_kft->tokenID);
+  g_free (processed_kft->reqHMACkey);
+  g_free (processed_kft->respHMACkey);
+  g_free (processed_kft->respXORkey);
+
+  g_slice_free (EphySyncCryptoProcessedKFT, processed_kft);
+}
+
+void
+ephy_sync_crypto_sync_keys_free (EphySyncCryptoSyncKeys *sync_keys)
+{
+  g_return_if_fail (sync_keys != NULL);
+
+  g_free (sync_keys->kA);
+  g_free (sync_keys->kB);
+  g_free (sync_keys->wrapKB);
+
+  g_slice_free (EphySyncCryptoSyncKeys, sync_keys);
+}
+
+static guint8 *
+xor (guint8 *a,
+     guint8 *b,
+     gsize   length)
+{
+  guint8 *xored;
+
+  xored = g_malloc (length);
+  for (gsize i = 0; i < length; i++)
+    xored[i] = a[i] ^ b[i];
+
+  return xored;
+}
+
+static gboolean
+are_equal (guint8 *a,
+           guint8 *b)
+{
+  gchar *a_hex;
+  gchar *b_hex;
+  gboolean retval;
+
+  a_hex = ephy_sync_utils_encode_hex (a, 0);
+  b_hex = ephy_sync_utils_encode_hex (b, 0);
+  retval = g_str_equal (a_hex, b_hex);
+
+  g_free (a_hex);
+  g_free (b_hex);
+
+  return retval;
+}
+
+static guint8 *
+sha256_hmac (guint8 *data,
+             gsize   data_length,
+             guint8 *key,
+             gsize   key_length)
+{
+  struct hmac_sha256_ctx ctx;
+  guint8 *digest;
+
+  digest = g_malloc (SHA256_DIGEST_SIZE);
+
+  hmac_sha256_set_key (&ctx, key_length, key);
+  hmac_sha256_update (&ctx, data_length, data);
+  hmac_sha256_digest (&ctx, SHA256_DIGEST_SIZE, digest);
+
+  return digest;
+}
+
 static gchar *
 generate_random_string (gsize length)
 {
@@ -237,7 +430,6 @@ calculate_mac (const gchar                 *mac_type,
                gsize                        key_length,
                EphySyncCryptoHawkArtifacts *artifacts)
 {
-  struct hmac_sha256_ctx ctx;
   guint8 *digest;
   gchar *normalized;
   gchar *mac;
@@ -247,11 +439,8 @@ calculate_mac (const gchar                 *mac_type,
   g_return_val_if_fail (artifacts, NULL);
 
   normalized = normalize_string (mac_type, artifacts);
-  digest = g_malloc (SHA256_DIGEST_SIZE);
-
-  hmac_sha256_set_key (&ctx, key_length, key);
-  hmac_sha256_update (&ctx, strlen (normalized), (guint8 *) normalized);
-  hmac_sha256_digest (&ctx, SHA256_DIGEST_SIZE, digest);
+  digest = sha256_hmac ((guint8 *) normalized, strlen (normalized),
+                        key, key_length);
   mac = g_base64_encode (digest, SHA256_DIGEST_SIZE);
 
   g_free (normalized);
@@ -278,69 +467,17 @@ append_token_to_header (gchar       *header,
   return new_header;
 }
 
-EphySyncCryptoHawkOptions *
-ephy_sync_crypto_hawk_options_new (gchar *app,
-                                   gchar *dlg,
-                                   gchar *ext,
-                                   gchar *content_type,
-                                   gchar *hash,
-                                   gchar *local_time_offset,
-                                   gchar *nonce,
-                                   gchar *payload,
-                                   gchar *timestamp)
-{
-  EphySyncCryptoHawkOptions *hawk_options;
-
-  hawk_options = g_slice_new (EphySyncCryptoHawkOptions);
-  hawk_options->app = app;
-  hawk_options->dlg = dlg;
-  hawk_options->ext = ext;
-  hawk_options->content_type = content_type;
-  hawk_options->hash = hash;
-  hawk_options->local_time_offset = local_time_offset;
-  hawk_options->nonce = nonce;
-  hawk_options->payload = payload;
-  hawk_options->timestamp = timestamp;
-
-  return hawk_options;
-}
-
-void
-ephy_sync_crypto_hawk_options_free (EphySyncCryptoHawkOptions *hawk_options)
-{
-  g_free (hawk_options->app);
-  g_free (hawk_options->dlg);
-  g_free (hawk_options->ext);
-  g_free (hawk_options->content_type);
-  g_free (hawk_options->hash);
-  g_free (hawk_options->local_time_offset);
-  g_free (hawk_options->nonce);
-  g_free (hawk_options->payload);
-  g_free (hawk_options->timestamp);
-
-  g_slice_free (EphySyncCryptoHawkOptions, hawk_options);
-}
-
-void
-ephy_sync_crypto_hawk_header_free (EphySyncCryptoHawkHeader *hawk_header)
-{
-  g_free (hawk_header->header);
-  ephy_sync_crypto_hawk_artifacts_free (hawk_header->artifacts);
-
-  g_slice_free (EphySyncCryptoHawkHeader, hawk_header);
-}
-
 /*
  * Runs 1000 iterations of PBKDF2.
  * Uses sha256 as hash function.
  */
-void
-ephy_sync_crypto_pbkdf2_1k (guint8 *key,
-                            gsize   key_length,
-                            guint8 *salt,
-                            gsize   salt_length,
-                            guint8 *out,
-                            gsize   out_length)
+static void
+pbkdf2_1k (guint8 *key,
+           gsize   key_length,
+           guint8 *salt,
+           gsize   salt_length,
+           guint8 *out,
+           gsize   out_length)
 {
   pbkdf2_hmac_sha256 (key_length, key, 1000, salt_length, salt, out_length, out);
 }
@@ -350,15 +487,15 @@ ephy_sync_crypto_pbkdf2_1k (guint8 *key,
  * Uses sha256 as hash function.
  * https://tools.ietf.org/html/rfc5869
  */
-void
-ephy_sync_crypto_hkdf (guint8 *in,
-                       gsize   in_length,
-                       guint8 *salt,
-                       gsize   salt_length,
-                       guint8 *info,
-                       gsize   info_length,
-                       guint8 *out,
-                       gsize   out_length)
+static void
+hkdf (guint8 *in,
+      gsize   in_length,
+      guint8 *salt,
+      gsize   salt_length,
+      guint8 *info,
+      gsize   info_length,
+      guint8 *out,
+      gsize   out_length)
 {
   struct hmac_sha256_ctx ctx;
   const gsize hash_length = 32;
@@ -403,6 +540,149 @@ ephy_sync_crypto_hkdf (guint8 *in,
   g_free (prk);
 }
 
+EphySyncCryptoStretchedCredentials *
+ephy_sync_crypto_stretch (const gchar *emailUTF8,
+                          const gchar *passwordUTF8)
+{
+  gchar *salt_stretch;
+  gchar *info_auth;
+  gchar *info_unwrap;
+  guint8 *quickStretchedPW;
+  guint8 *authPW;
+  guint8 *unwrapBKey;
+
+  salt_stretch = ephy_sync_utils_kwe ("quickStretch", emailUTF8);
+  quickStretchedPW = g_malloc (EPHY_SYNC_TOKEN_LENGTH);
+  pbkdf2_1k ((guint8 *) passwordUTF8, strlen (passwordUTF8),
+             (guint8 *) salt_stretch, strlen (salt_stretch),
+             quickStretchedPW, EPHY_SYNC_TOKEN_LENGTH);
+
+  info_auth = ephy_sync_utils_kw ("authPW");
+  authPW = g_malloc (EPHY_SYNC_TOKEN_LENGTH);
+  hkdf (quickStretchedPW, EPHY_SYNC_TOKEN_LENGTH,
+        NULL, 0,
+        (guint8 *) info_auth, strlen (info_auth),
+        authPW, EPHY_SYNC_TOKEN_LENGTH);
+
+  info_unwrap = ephy_sync_utils_kw ("unwrapBkey");
+  unwrapBKey = g_malloc (EPHY_SYNC_TOKEN_LENGTH);
+  hkdf (quickStretchedPW, EPHY_SYNC_TOKEN_LENGTH,
+        NULL, 0,
+        (guint8 *) info_unwrap, strlen (info_unwrap),
+        unwrapBKey, EPHY_SYNC_TOKEN_LENGTH);
+
+  g_free (salt_stretch);
+  g_free (info_unwrap);
+  g_free (info_auth);
+
+  return ephy_sync_crypto_stretched_credentials_new (quickStretchedPW,
+                                                     authPW,
+                                                     unwrapBKey);
+}
+
+EphySyncCryptoProcessedKFT *
+ephy_sync_crypto_process_key_fetch_token (const gchar *keyFetchToken)
+{
+  guint8 *kft;
+  guint8 *out1;
+  guint8 *out2;
+  guint8 *tokenID;
+  guint8 *reqHMACkey;
+  guint8 *respHMACkey;
+  guint8 *respXORkey;
+  guint8 *keyRequestKey;
+  gchar *info_kft;
+  gchar *info_keys;
+
+  kft = ephy_sync_utils_decode_hex (keyFetchToken);
+  info_kft = ephy_sync_utils_kw ("keyFetchToken");
+  info_keys = ephy_sync_utils_kw ("account/keys");
+  out1 = g_malloc (3 * EPHY_SYNC_TOKEN_LENGTH);
+  out2 = g_malloc (3 * EPHY_SYNC_TOKEN_LENGTH);
+
+  hkdf (kft, EPHY_SYNC_TOKEN_LENGTH,
+        NULL, 0,
+        (guint8 *) info_kft, strlen (info_kft),
+        out1, 3 * EPHY_SYNC_TOKEN_LENGTH);
+
+  tokenID = g_malloc (EPHY_SYNC_TOKEN_LENGTH);
+  reqHMACkey = g_malloc (EPHY_SYNC_TOKEN_LENGTH);
+  keyRequestKey = g_malloc (EPHY_SYNC_TOKEN_LENGTH);
+  memcpy (tokenID, out1, EPHY_SYNC_TOKEN_LENGTH);
+  memcpy (reqHMACkey, out1 + EPHY_SYNC_TOKEN_LENGTH, EPHY_SYNC_TOKEN_LENGTH);
+  memcpy (keyRequestKey, out1 + 2 * EPHY_SYNC_TOKEN_LENGTH, EPHY_SYNC_TOKEN_LENGTH);
+
+  hkdf (keyRequestKey, EPHY_SYNC_TOKEN_LENGTH,
+        NULL, 0,
+        (guint8 *) info_keys, strlen (info_keys),
+        out2, 3 * EPHY_SYNC_TOKEN_LENGTH);
+
+  respHMACkey = g_malloc (EPHY_SYNC_TOKEN_LENGTH);
+  respXORkey = g_malloc (2 * EPHY_SYNC_TOKEN_LENGTH);
+  memcpy (respHMACkey, out2, EPHY_SYNC_TOKEN_LENGTH);
+  memcpy (respXORkey, out2 + EPHY_SYNC_TOKEN_LENGTH, 2 * EPHY_SYNC_TOKEN_LENGTH);
+
+  g_free (kft);
+  g_free (out1);
+  g_free (out2);
+  g_free (info_kft);
+  g_free (info_keys);
+  g_free (keyRequestKey);
+
+  return ephy_sync_crypto_processed_kft_new (tokenID,
+                                             reqHMACkey,
+                                             respHMACkey,
+                                             respXORkey);
+}
+
+EphySyncCryptoSyncKeys *
+ephy_sync_crypto_retrieve_sync_keys (const gchar *bundle,
+                                     guint8      *respHMACkey,
+                                     guint8      *respXORkey,
+                                     guint8      *unwrapBKey)
+{
+  guint8 *bdl;
+  guint8 *ciphertext;
+  guint8 *respMAC;
+  guint8 *respMAC2;
+  guint8 *xored;
+  guint8 *wrapKB;
+  guint8 *kA;
+  guint8 *kB;
+  EphySyncCryptoSyncKeys *retval = NULL;
+
+  bdl = ephy_sync_utils_decode_hex (bundle);
+  ciphertext = g_malloc (2 * EPHY_SYNC_TOKEN_LENGTH);
+  respMAC = g_malloc (EPHY_SYNC_TOKEN_LENGTH);
+  wrapKB = g_malloc (EPHY_SYNC_TOKEN_LENGTH);
+  kA = g_malloc (EPHY_SYNC_TOKEN_LENGTH);
+
+  memcpy (ciphertext, bdl, 2 * EPHY_SYNC_TOKEN_LENGTH);
+  memcpy (respMAC, bdl + 2 * EPHY_SYNC_TOKEN_LENGTH, EPHY_SYNC_TOKEN_LENGTH);
+  respMAC2 = sha256_hmac (ciphertext, 2 * EPHY_SYNC_TOKEN_LENGTH,
+                          respHMACkey, EPHY_SYNC_TOKEN_LENGTH);
+
+  if (are_equal (respMAC, respMAC2) == FALSE) {
+    g_warning ("respMAC and respMAC2 differ");
+    goto out;
+  }
+
+  xored = xor (ciphertext, respXORkey, 2 * EPHY_SYNC_TOKEN_LENGTH);
+  memcpy (kA, xored, EPHY_SYNC_TOKEN_LENGTH);
+  memcpy (wrapKB, xored + EPHY_SYNC_TOKEN_LENGTH, EPHY_SYNC_TOKEN_LENGTH);
+  kB = xor (unwrapBKey, wrapKB, EPHY_SYNC_TOKEN_LENGTH);
+  retval = ephy_sync_crypto_sync_keys_new (kA, kB, wrapKB);
+
+out:
+  g_free (bdl);
+  g_free (ciphertext);
+  g_free (respMAC);
+  g_free (respMAC2);
+  g_free (xored);
+
+  return retval;
+}
+
 EphySyncCryptoHawkHeader *
 ephy_sync_crypto_compute_hawk_header (const gchar               *url,
                                       const gchar               *method,
diff --git a/src/ephy-sync-crypto.h b/src/ephy-sync-crypto.h
index 7afb73d..2e3c789 100644
--- a/src/ephy-sync-crypto.h
+++ b/src/ephy-sync-crypto.h
@@ -53,42 +53,61 @@ typedef struct {
   EphySyncCryptoHawkArtifacts *artifacts;
 } EphySyncCryptoHawkHeader;
 
-void                       ephy_sync_crypto_pbkdf2_1k           (guint8 *key,
-                                                                 gsize   key_length,
-                                                                 guint8 *salt,
-                                                                 gsize   salt_length,
-                                                                 guint8 *out,
-                                                                 gsize   out_length);
-
-void                       ephy_sync_crypto_hkdf                (guint8 *in,
-                                                                 gsize   in_length,
-                                                                 guint8 *salt,
-                                                                 gsize   salt_length,
-                                                                 guint8 *info,
-                                                                 gsize   info_length,
-                                                                 guint8 *out,
-                                                                 gsize   out_length);
-
-EphySyncCryptoHawkHeader  *ephy_sync_crypto_compute_hawk_header (const gchar               *url,
-                                                                 const gchar               *method,
-                                                                 const gchar               *id,
-                                                                 guint8                    *key,
-                                                                 gsize                      key_length,
-                                                                 EphySyncCryptoHawkOptions *options);
-
-EphySyncCryptoHawkOptions *ephy_sync_crypto_hawk_options_new    (gchar *app,
-                                                                 gchar *dlg,
-                                                                 gchar *ext,
-                                                                 gchar *content_type,
-                                                                 gchar *hash,
-                                                                 gchar *local_time_offset,
-                                                                 gchar *nonce,
-                                                                 gchar *payload,
-                                                                 gchar *timestamp);
-
-void                       ephy_sync_crypto_hawk_options_free   (EphySyncCryptoHawkOptions *hawk_options);
-
-void                       ephy_sync_crypto_hawk_header_free    (EphySyncCryptoHawkHeader *hawk_header);
+typedef struct {
+  guint8 *quickStretchedPW;
+  guint8 *authPW;
+  guint8 *unwrapBKey;
+} EphySyncCryptoStretchedCredentials;
+
+typedef struct {
+  guint8 *tokenID;
+  guint8 *reqHMACkey;
+  guint8 *respHMACkey;
+  guint8 *respXORkey;
+} EphySyncCryptoProcessedKFT;
+
+typedef struct {
+  guint8 *kA;
+  guint8 *kB;
+  guint8 *wrapKB;
+} EphySyncCryptoSyncKeys;
+
+EphySyncCryptoHawkOptions          *ephy_sync_crypto_hawk_options_new           (gchar *app,
+                                                                                 gchar *dlg,
+                                                                                 gchar *ext,
+                                                                                 gchar *content_type,
+                                                                                 gchar *hash,
+                                                                                 gchar *local_time_offset,
+                                                                                 gchar *nonce,
+                                                                                 gchar *payload,
+                                                                                 gchar *timestamp);
+
+void                                ephy_sync_crypto_hawk_options_free          (EphySyncCryptoHawkOptions 
*hawk_options);
+
+void                                ephy_sync_crypto_hawk_header_free           (EphySyncCryptoHawkHeader 
*hawk_header);
+
+void                                ephy_sync_crypto_stretched_credentials_free 
(EphySyncCryptoStretchedCredentials *stretched_credentials);
+
+void                                ephy_sync_crypto_processed_kft_free         (EphySyncCryptoProcessedKFT 
*processed_kft);
+
+void                                ephy_sync_crypto_sync_keys_free             (EphySyncCryptoSyncKeys 
*sync_keys);
+
+EphySyncCryptoStretchedCredentials *ephy_sync_crypto_stretch                    (const gchar *emailUTF8,
+                                                                                 const gchar *passwordUTF8);
+
+EphySyncCryptoProcessedKFT         *ephy_sync_crypto_process_key_fetch_token    (const gchar  
*keyFetchToken);
+
+EphySyncCryptoSyncKeys             *ephy_sync_crypto_retrieve_sync_keys         (const gchar *bundle,
+                                                                                 guint8      *respHMACkey,
+                                                                                 guint8      *respXORkey,
+                                                                                 guint8      *unwrapBKey);
+
+EphySyncCryptoHawkHeader           *ephy_sync_crypto_compute_hawk_header        (const gchar               
*url,
+                                                                                 const gchar               
*method,
+                                                                                 const gchar               
*id,
+                                                                                 guint8                    
*key,
+                                                                                 gsize                      
key_length,
+                                                                                 EphySyncCryptoHawkOptions 
*options);
 
 G_END_DECLS
 
diff --git a/src/ephy-sync-secret.c b/src/ephy-sync-secret.c
index 4b430dd..29ca050 100644
--- a/src/ephy-sync-secret.c
+++ b/src/ephy-sync-secret.c
@@ -123,7 +123,7 @@ ephy_sync_secret_load_tokens (EphySyncService *sync_service)
     if (g_strcmp0 (emailUTF8, user_email))
       continue;
 
-    ephy_sync_service_save_token (sync_service, token_type, g_strdup (token_value));
+    ephy_sync_service_save_token (sync_service, g_strdup (token_value), token_type);
 LOG ("[%d] Loaded token %s with value %s for email %s", __LINE__, token_name, token_value, emailUTF8);
 
     g_hash_table_unref (attributes);
@@ -134,8 +134,8 @@ LOG ("[%d] Loaded token %s with value %s for email %s", __LINE__, token_name, to
 
 void
 ephy_sync_secret_store_token (const gchar       *emailUTF8,
-                              EphySyncTokenType  token_type,
-                              gchar             *token_value)
+                              gchar             *token_value,
+                              EphySyncTokenType  token_type)
 {
   SecretValue *secret_value;
   GHashTable *attributes;
diff --git a/src/ephy-sync-secret.h b/src/ephy-sync-secret.h
index 5885f77..b5826b5 100644
--- a/src/ephy-sync-secret.h
+++ b/src/ephy-sync-secret.h
@@ -39,8 +39,8 @@ void ephy_sync_secret_forget_all_tokens (void);
 void ephy_sync_secret_load_tokens       (EphySyncService *sync_service);
 
 void ephy_sync_secret_store_token       (const gchar       *emailUTF8,
-                                         EphySyncTokenType  token_type,
-                                         gchar             *token_value);
+                                         gchar             *token_value,
+                                         EphySyncTokenType  token_type);
 
 G_END_DECLS
 
diff --git a/src/ephy-sync-service.c b/src/ephy-sync-service.c
index 04910e1..aa4f4f3 100644
--- a/src/ephy-sync-service.c
+++ b/src/ephy-sync-service.c
@@ -24,17 +24,20 @@
 #include "ephy-sync-service.h"
 #include "ephy-sync-utils.h"
 
+#include <glib/gi18n.h>
 #include <json-glib/json-glib.h>
 #include <libsoup/soup.h>
 #include <string.h>
 
 #define FXA_BASEURL   "https://api.accounts.firefox.com/";
 #define FXA_VERSION   "v1/"
+#define STATUS_OK     200
 
 struct _EphySyncService {
   GObject parent_instance;
 
   SoupSession *soup_session;
+  JsonParser *parser;
 
   gchar *user_email;
   GHashTable *tokens;
@@ -43,15 +46,23 @@ struct _EphySyncService {
 
 G_DEFINE_TYPE (EphySyncService, ephy_sync_service, G_TYPE_OBJECT);
 
-static SoupMessage *
-synchronous_hawk_get_request (EphySyncService *self,
-                              const gchar     *endpoint,
-                              const gchar     *id,
-                              guint8          *key,
-                              gsize            key_length)
+static void
+save_and_store_tokens (EphySyncService   *self,
+                       gchar             *token_value,
+                       EphySyncTokenType  token_type,
+                       ...) G_GNUC_NULL_TERMINATED;
+
+static guint
+synchronous_hawk_get_request (EphySyncService  *self,
+                              const gchar      *endpoint,
+                              const gchar      *id,
+                              guint8           *key,
+                              gsize             key_length,
+                              JsonObject      **jobject)
 {
   EphySyncCryptoHawkHeader *hawk_header;
   SoupMessage *message;
+  JsonNode *root;
   gchar *url;
 
   url = g_strdup_printf ("%s%s%s", FXA_BASEURL, FXA_VERSION, endpoint);
@@ -64,24 +75,34 @@ synchronous_hawk_get_request (EphySyncService *self,
                                "authorization", hawk_header->header);
 LOG ("[%d] Sending synchronous HAWK GET request to %s endpoint", __LINE__, endpoint);
   soup_session_send_message (self->soup_session, message);
+LOG ("[%d] Got response from server: %u", __LINE__, message->status_code);
+
+  json_parser_load_from_data (self->parser,
+                              message->response_body->data,
+                              -1, NULL);
+  root = json_parser_get_root (self->parser);
+  g_assert (JSON_NODE_HOLDS_OBJECT (root));
+  *jobject = json_node_get_object (root);
 
   g_free (url);
   ephy_sync_crypto_hawk_header_free (hawk_header);
 
-  return message;
+  return message->status_code;
 }
 
-static SoupMessage *
-synchronous_hawk_post_request (EphySyncService *self,
-                               const gchar     *endpoint,
-                               const gchar     *id,
-                               guint8          *key,
-                               gsize            key_length,
-                               gchar           *request_body)
+static guint
+synchronous_hawk_post_request (EphySyncService  *self,
+                               const gchar      *endpoint,
+                               const gchar      *id,
+                               guint8           *key,
+                               gsize             key_length,
+                               gchar            *request_body,
+                               JsonObject      **jobject)
 {
   EphySyncCryptoHawkHeader *hawk_header;
   EphySyncCryptoHawkOptions *hawk_options;
   SoupMessage *message;
+  JsonNode *root;
   gchar *url;
 
   url = g_strdup_printf ("%s%s%s", FXA_BASEURL, FXA_VERSION, endpoint);
@@ -106,20 +127,30 @@ synchronous_hawk_post_request (EphySyncService *self,
                                "content-type", "application/json");
 LOG ("[%d] Sending synchronous HAWK POST request to %s endpoint", __LINE__, endpoint);
   soup_session_send_message (self->soup_session, message);
+LOG ("[%d] Got response from server: %u", __LINE__, message->status_code);
+
+  json_parser_load_from_data (self->parser,
+                              message->response_body->data,
+                              -1, NULL);
+  root = json_parser_get_root (self->parser);
+  g_assert (JSON_NODE_HOLDS_OBJECT (root));
+  *jobject = json_node_get_object (root);
 
   g_free (url);
   ephy_sync_crypto_hawk_options_free (hawk_options);
   ephy_sync_crypto_hawk_header_free (hawk_header);
 
-  return message;
+  return message->status_code;
 }
 
-static SoupMessage *
-synchronous_fxa_post_request (EphySyncService *self,
-                              const gchar     *endpoint,
-                              gchar           *request_body)
+static guint
+synchronous_fxa_post_request (EphySyncService  *self,
+                              const gchar      *endpoint,
+                              gchar            *request_body,
+                              JsonObject      **jobject)
 {
   SoupMessage *message;
+  JsonNode *root;
   gchar *url;
 
   url = g_strdup_printf ("%s%s%s", FXA_BASEURL, FXA_VERSION, endpoint);
@@ -131,10 +162,40 @@ synchronous_fxa_post_request (EphySyncService *self,
                             strlen (request_body));
 LOG ("[%d] Sending synchronous POST request to %s endpoint", __LINE__, endpoint);
   soup_session_send_message (self->soup_session, message);
+LOG ("[%d] Got response from server: %u", __LINE__, message->status_code);
+
+  json_parser_load_from_data (self->parser,
+                              message->response_body->data,
+                              -1, NULL);
+  root = json_parser_get_root (self->parser);
+  g_assert (JSON_NODE_HOLDS_OBJECT (root));
+  *jobject = json_node_get_object (root);
 
   g_free (url);
 
-  return message;
+  return message->status_code;
+}
+
+static void
+save_and_store_tokens (EphySyncService   *self,
+                       gchar             *token_value,
+                       EphySyncTokenType  token_type,
+                       ...)
+{
+  EphySyncTokenType type;
+  gchar *value;
+  va_list args;
+
+  ephy_sync_service_save_token (self, token_value, token_type);
+  ephy_sync_secret_store_token (self->user_email, token_value, token_type);
+
+  va_start (args, token_type);
+  while ((value = va_arg (args, gchar *)) != NULL) {
+    type = va_arg (args, EphySyncTokenType);
+    ephy_sync_service_save_token (self, value, type);
+    ephy_sync_secret_store_token (self->user_email, value, type);
+  }
+  va_end (args);
 }
 
 static void
@@ -145,6 +206,7 @@ ephy_sync_service_finalize (GObject *object)
   g_free (self->user_email);
   g_hash_table_destroy (self->tokens);
   g_clear_object (&self->soup_session);
+  g_clear_object (&self->parser);
 
   G_OBJECT_CLASS (ephy_sync_service_parent_class)->finalize (object);
 }
@@ -165,6 +227,7 @@ ephy_sync_service_init (EphySyncService *self)
   self->tokens = g_hash_table_new_full (g_str_hash, g_str_equal,
                                         NULL, g_free);
   self->soup_session = soup_session_new ();
+  self->parser = json_parser_new ();
 
   sync_user = g_settings_get_string (EPHY_SETTINGS_MAIN,
                                      EPHY_PREFS_SYNC_USER);
@@ -215,8 +278,8 @@ LOG ("[%d] Returning token %s with value %s", __LINE__, token_name, token_value)
 
 void
 ephy_sync_service_save_token (EphySyncService   *self,
-                              EphySyncTokenType  token_type,
-                              gchar             *token_value)
+                              gchar             *token_value,
+                              EphySyncTokenType  token_type)
 {
   const gchar *token_name;
 
@@ -251,154 +314,114 @@ LOG ("[%d] Deleted all tokens", __LINE__);
 
 gboolean
 ephy_sync_service_login (EphySyncService  *self,
-                         guint            *error_code,
+                         const gchar      *emailUTF8,
+                         const gchar      *passwordUTF8,
                          gchar           **error_message)
 {
-  SoupMessage *message;
-  JsonParser *parser;
-  JsonNode *root;
-  JsonObject *object;
+  EphySyncCryptoStretchedCredentials *stretched_credentials = NULL;
+  EphySyncCryptoProcessedKFT *processed_kft = NULL;
+  EphySyncCryptoSyncKeys *sync_keys = NULL;
+  JsonObject *jobject;
   gchar *request_body;
-  gchar *quickStretchedPW;
-  gchar *authPW;
-  gchar *unwrapBKey;
-  gchar *uid;
-  gchar *sessionToken;
-  gchar *keyFetchToken;
-
-  authPW = ephy_sync_service_get_token (self, EPHY_SYNC_TOKEN_AUTHPW);
-  g_return_val_if_fail (authPW, FALSE);
-
+  gchar *tokenID = NULL;
+  gchar *authPW = NULL;
+  gchar *unwrapBKey = NULL;
+  gchar *uid = NULL;
+  gchar *sessionToken = NULL;
+  gchar *keyFetchToken = NULL;
+  gchar *kA = NULL;
+  gchar *kB = NULL;
+  gchar *wrapKB = NULL;
+  guint status_code;
+  gboolean retval = FALSE;
+
+  stretched_credentials = ephy_sync_crypto_stretch (emailUTF8, passwordUTF8);
+  authPW = ephy_sync_utils_encode_hex (stretched_credentials->authPW, 0);
   request_body = ephy_sync_utils_build_json_string ("authPW", authPW,
-                                                    "email", self->user_email,
+                                                    "email", emailUTF8,
                                                     NULL);
-  message = synchronous_fxa_post_request (self,
-                                          "account/login?keys=true",
-                                          request_body);
-LOG ("[%d] status code: %u", __LINE__, message->status_code);
-
-  parser = json_parser_new ();
-  json_parser_load_from_data (parser, message->response_body->data, -1, NULL);
-  root = json_parser_get_root (parser);
-  g_assert (JSON_NODE_HOLDS_OBJECT (root));
-  object = json_node_get_object (root);
-
-  if (message->status_code != 200) {
-    *error_message = g_strdup (json_object_get_string_member (object, "message"));
-    *error_code = json_object_get_int_member (object, "errno");
-
-LOG ("[%d] errno: %u, errmsg: %s", __LINE__, *error_code, *error_message);
-
-    ephy_sync_service_delete_all_tokens (self);
-    ephy_sync_service_set_user_email (self, NULL);
-
-    return FALSE;
+  status_code = synchronous_fxa_post_request (self,
+                                              "account/login?keys=true",
+                                              request_body,
+                                              &jobject);
+  if (status_code != STATUS_OK) {
+    g_warning ("FxA server errno: %ld, errmsg: %s",
+               json_object_get_int_member (jobject, "errno"),
+               json_object_get_string_member (jobject, "message"));
+    *error_message = g_strdup_printf ("%s.",
+                                      json_object_get_string_member (jobject, "message"));
+    g_free (authPW);
+    goto out;
+  } else if (json_object_get_boolean_member (jobject, "verified") == FALSE) {
+    g_warning ("Firefox Account not verified");
+    *error_message = g_strdup (_("Account not verified!"));
+    g_free (authPW);
+    goto out;
   }
 
-  /* Extract uid, sesionToken, keyFetchToken */
-  uid = g_strdup (json_object_get_string_member (object, "uid"));
-  sessionToken = g_strdup (json_object_get_string_member (object, "sessionToken"));
-  keyFetchToken = g_strdup (json_object_get_string_member (object, "keyFetchToken"));
-
-  /* Save tokens in memory */
-  ephy_sync_service_save_token (self,
-                                EPHY_SYNC_TOKEN_UID,
-                                uid);
-  ephy_sync_service_save_token (self,
-                                EPHY_SYNC_TOKEN_SESSIONTOKEN,
-                                sessionToken);
-  ephy_sync_service_save_token (self,
-                                EPHY_SYNC_TOKEN_KEYFETCHTOKEN,
-                                keyFetchToken);
-
-  /* Store tokens on disk */
-  quickStretchedPW = ephy_sync_service_get_token (self, EPHY_SYNC_TOKEN_QUICKSTRETCHEDPW);
-  unwrapBKey = ephy_sync_service_get_token (self, EPHY_SYNC_TOKEN_UNWRAPBKEY);
-  ephy_sync_secret_store_token (self->user_email,
-                                EPHY_SYNC_TOKEN_AUTHPW,
-                                authPW);
-  ephy_sync_secret_store_token (self->user_email,
-                                EPHY_SYNC_TOKEN_KEYFETCHTOKEN,
-                                keyFetchToken);
-  ephy_sync_secret_store_token (self->user_email,
-                                EPHY_SYNC_TOKEN_SESSIONTOKEN,
-                                sessionToken);
-  ephy_sync_secret_store_token (self->user_email,
-                                EPHY_SYNC_TOKEN_UID,
-                                uid);
-  ephy_sync_secret_store_token (self->user_email,
-                                EPHY_SYNC_TOKEN_UNWRAPBKEY,
-                                unwrapBKey);
-  ephy_sync_secret_store_token (self->user_email,
-                                EPHY_SYNC_TOKEN_QUICKSTRETCHEDPW,
-                                quickStretchedPW);
-
-  return TRUE;
-}
+  uid = g_strdup (json_object_get_string_member (jobject, "uid"));
+  sessionToken = g_strdup (json_object_get_string_member (jobject, "sessionToken"));
+  keyFetchToken = g_strdup (json_object_get_string_member (jobject, "keyFetchToken"));
+
+  /* Proceed with key fetching */
+  processed_kft = ephy_sync_crypto_process_key_fetch_token (keyFetchToken);
+  tokenID = ephy_sync_utils_encode_hex (processed_kft->tokenID, 0);
+  status_code = synchronous_hawk_get_request (self,
+                                              "account/keys",
+                                              tokenID,
+                                              processed_kft->reqHMACkey,
+                                              EPHY_SYNC_TOKEN_LENGTH,
+                                              &jobject);
+  if (status_code != STATUS_OK) {
+    g_warning ("FxA server errno: %ld, errmsg: %s",
+               json_object_get_int_member (jobject, "errno"),
+               json_object_get_string_member (jobject, "message"));
+    /* Translators: the %s refers to the error message. */
+    *error_message = g_strdup_printf (_("Failed to retrieve keys: %s. Please try again."),
+                                      json_object_get_string_member (jobject, "message"));
+    g_free (authPW);
+    g_free (uid);
+    g_free (sessionToken);
+    g_free (keyFetchToken);
+    goto out;
+  }
 
-void
-ephy_sync_service_stretch (EphySyncService *self,
-                           const gchar     *emailUTF8,
-                           const gchar     *passwordUTF8)
-{
-  gchar *salt_stretch;
-  gchar *info_auth;
-  gchar *info_unwrap;
-  guint8 *quickStretchedPW;
-  guint8 *authPW;
-  guint8 *unwrapBKey;
-
-  salt_stretch = ephy_sync_utils_kwe ("quickStretch", emailUTF8);
-  quickStretchedPW = g_malloc (EPHY_SYNC_TOKEN_LENGTH);
-  ephy_sync_crypto_pbkdf2_1k ((guint8 *) passwordUTF8,
-                              strlen (passwordUTF8),
-                              (guint8 *) salt_stretch,
-                              strlen (salt_stretch),
-                              quickStretchedPW,
-                              EPHY_SYNC_TOKEN_LENGTH);
-
-ephy_sync_utils_display_hex ("quickStretchedPW", quickStretchedPW, EPHY_SYNC_TOKEN_LENGTH);
-
-  info_auth = ephy_sync_utils_kw ("authPW");
-  authPW = g_malloc (EPHY_SYNC_TOKEN_LENGTH);
-  ephy_sync_crypto_hkdf (quickStretchedPW,
-                         EPHY_SYNC_TOKEN_LENGTH,
-                         NULL, 0,
-                         (guint8 *) info_auth,
-                         strlen (info_auth),
-                         authPW,
-                         EPHY_SYNC_TOKEN_LENGTH);
-
-  info_unwrap = ephy_sync_utils_kw ("unwrapBkey");
-  unwrapBKey = g_malloc (EPHY_SYNC_TOKEN_LENGTH);
-  ephy_sync_crypto_hkdf (quickStretchedPW,
-                         EPHY_SYNC_TOKEN_LENGTH,
-                         NULL, 0,
-                         (guint8 *) info_unwrap,
-                         strlen (info_unwrap),
-                         unwrapBKey,
-                         EPHY_SYNC_TOKEN_LENGTH);
-
-LOG ("[%d] Stretching done", __LINE__);
+  sync_keys = ephy_sync_crypto_retrieve_sync_keys (json_object_get_string_member (jobject, "bundle"),
+                                                   processed_kft->respHMACkey,
+                                                   processed_kft->respXORkey,
+                                                   stretched_credentials->unwrapBKey);
+  if (sync_keys == NULL) {
+    *error_message = g_strdup (_("Something went wrong, please try again."));
+    g_free (authPW);
+    g_free (uid);
+    g_free (sessionToken);
+    g_free (keyFetchToken);
+    goto out;
+  }
 
+  /* Everything okay, save and store tokens */
   ephy_sync_service_set_user_email (self, emailUTF8);
-  ephy_sync_service_save_token (self,
-                                EPHY_SYNC_TOKEN_QUICKSTRETCHEDPW,
-                                ephy_sync_utils_encode_hex (quickStretchedPW,
-                                                            EPHY_SYNC_TOKEN_LENGTH));
-  ephy_sync_service_save_token (self,
-                                EPHY_SYNC_TOKEN_AUTHPW,
-                                ephy_sync_utils_encode_hex (authPW,
-                                                            EPHY_SYNC_TOKEN_LENGTH));
-  ephy_sync_service_save_token (self,
-                                EPHY_SYNC_TOKEN_UNWRAPBKEY,
-                                ephy_sync_utils_encode_hex (unwrapBKey,
-                                                            EPHY_SYNC_TOKEN_LENGTH));
-
-  g_free (salt_stretch);
-  g_free (info_unwrap);
-  g_free (info_auth);
-  g_free (quickStretchedPW);
-  g_free (authPW);
-  g_free (unwrapBKey);
+  unwrapBKey = ephy_sync_utils_encode_hex (stretched_credentials->unwrapBKey, 0);
+  kA = ephy_sync_utils_encode_hex (sync_keys->kA, 0);
+  kB = ephy_sync_utils_encode_hex (sync_keys->kB, 0);
+  wrapKB = ephy_sync_utils_encode_hex (sync_keys->wrapKB, 0);
+  save_and_store_tokens (self,
+                         authPW, EPHY_SYNC_TOKEN_AUTHPW,
+                         unwrapBKey, EPHY_SYNC_TOKEN_UNWRAPBKEY,
+                         uid, EPHY_SYNC_TOKEN_UID,
+                         sessionToken, EPHY_SYNC_TOKEN_SESSIONTOKEN,
+                         keyFetchToken, EPHY_SYNC_TOKEN_KEYFETCHTOKEN,
+                         kA, EPHY_SYNC_TOKEN_KA,
+                         kB, EPHY_SYNC_TOKEN_KB,
+                         wrapKB, EPHY_SYNC_TOKEN_WRAPKB,
+                         NULL);
+  retval = TRUE;
+
+out:
+  ephy_sync_crypto_stretched_credentials_free (stretched_credentials);
+  ephy_sync_crypto_processed_kft_free (processed_kft);
+  ephy_sync_crypto_sync_keys_free (sync_keys);
+  g_free (tokenID);
+
+  return retval;
 }
diff --git a/src/ephy-sync-service.h b/src/ephy-sync-service.h
index 2631971..ffe63eb 100644
--- a/src/ephy-sync-service.h
+++ b/src/ephy-sync-service.h
@@ -40,20 +40,17 @@ gchar           *ephy_sync_service_get_token         (EphySyncService   *self,
                                                       EphySyncTokenType  token_type);
 
 void             ephy_sync_service_save_token        (EphySyncService   *self,
-                                                      EphySyncTokenType  token_type,
-                                                      gchar             *token_value);
+                                                      gchar             *token_value,
+                                                      EphySyncTokenType  token_type);
 
 void             ephy_sync_service_delete_token      (EphySyncService   *self,
                                                       EphySyncTokenType  token_type);
 
 void             ephy_sync_service_delete_all_tokens (EphySyncService *self);
 
-void             ephy_sync_service_stretch           (EphySyncService *self,
-                                                      const gchar     *emailUTF8,
-                                                      const gchar     *passwordUTF8);
-
 gboolean         ephy_sync_service_login             (EphySyncService  *self,
-                                                      guint            *error_code,
+                                                      const gchar      *emailUTF8,
+                                                      const gchar      *passwordUTF8,
                                                       gchar           **error_message);
 
 G_END_DECLS
diff --git a/src/ephy-sync-utils.c b/src/ephy-sync-utils.c
index c307b0b..784b78e 100644
--- a/src/ephy-sync-utils.c
+++ b/src/ephy-sync-utils.c
@@ -41,16 +41,20 @@ gchar *
 ephy_sync_utils_encode_hex (guint8 *data,
                             gsize   data_length)
 {
-  gchar *retval = g_malloc (data_length * 2 + 1);
+  gchar *retval;
+  gsize length;
 
-  for (gsize i = 0; i < data_length; i++) {
+  length = data_length == 0 ? EPHY_SYNC_TOKEN_LENGTH : data_length;
+  retval = g_malloc (length * 2 + 1);
+
+  for (gsize i = 0; i < length; i++) {
     guint8 byte = data[i];
 
     retval[2 * i] = hex_digits[byte >> 4];
     retval[2 * i + 1] = hex_digits[byte & 0xf];
   }
 
-  retval[data_length * 2] = 0;
+  retval[length * 2] = 0;
 
   return retval;
 }
@@ -59,8 +63,9 @@ guint8 *
 ephy_sync_utils_decode_hex (const gchar *hex_string)
 {
   guint8 *retval;
-  gsize hex_length = strlen (hex_string);
+  gsize hex_length;
 
+  hex_length = strlen (hex_string);
   g_return_val_if_fail (hex_length % 2 == 0, NULL);
 
   retval = g_malloc (hex_length / 2);
@@ -77,17 +82,21 @@ ephy_sync_utils_token_name_from_type (EphySyncTokenType token_type)
 {
   switch (token_type) {
   case EPHY_SYNC_TOKEN_AUTHPW:
-    return "authPw";
-  case EPHY_SYNC_TOKEN_KEYFETCHTOKEN:
-    return "keyFetchToken";
-  case EPHY_SYNC_TOKEN_SESSIONTOKEN:
-    return "sessionToken";
-  case EPHY_SYNC_TOKEN_UID:
-    return "uid";
+    return "authPW";
   case EPHY_SYNC_TOKEN_UNWRAPBKEY:
     return "unwrapBKey";
-  case EPHY_SYNC_TOKEN_QUICKSTRETCHEDPW:
-    return "quickStretchedPW";
+  case EPHY_SYNC_TOKEN_UID:
+    return "uid";
+  case EPHY_SYNC_TOKEN_SESSIONTOKEN:
+    return "sessionToken";
+  case EPHY_SYNC_TOKEN_KEYFETCHTOKEN:
+    return "keyFetchToken";
+  case EPHY_SYNC_TOKEN_KA:
+    return "kA";
+  case EPHY_SYNC_TOKEN_KB:
+    return "kB";
+  case EPHY_SYNC_TOKEN_WRAPKB:
+    return "wrapKB";
   default:
     g_assert_not_reached ();
   }
diff --git a/src/ephy-sync-utils.h b/src/ephy-sync-utils.h
index 9e33850..a0ee2ec 100644
--- a/src/ephy-sync-utils.h
+++ b/src/ephy-sync-utils.h
@@ -27,11 +27,13 @@ G_BEGIN_DECLS
 
 typedef enum {
   EPHY_SYNC_TOKEN_AUTHPW,
-  EPHY_SYNC_TOKEN_KEYFETCHTOKEN,
-  EPHY_SYNC_TOKEN_SESSIONTOKEN,
-  EPHY_SYNC_TOKEN_UID,
   EPHY_SYNC_TOKEN_UNWRAPBKEY,
-  EPHY_SYNC_TOKEN_QUICKSTRETCHEDPW
+  EPHY_SYNC_TOKEN_UID,
+  EPHY_SYNC_TOKEN_SESSIONTOKEN,
+  EPHY_SYNC_TOKEN_KEYFETCHTOKEN,
+  EPHY_SYNC_TOKEN_KA,
+  EPHY_SYNC_TOKEN_KB,
+  EPHY_SYNC_TOKEN_WRAPKB
 } EphySyncTokenType;
 
 gchar       *ephy_sync_utils_kw                   (const gchar *name);
diff --git a/src/prefs-dialog.c b/src/prefs-dialog.c
index 452d8ee..0117edf 100644
--- a/src/prefs-dialog.c
+++ b/src/prefs-dialog.c
@@ -35,6 +35,7 @@
 #include "ephy-session.h"
 #include "ephy-settings.h"
 #include "ephy-shell.h"
+#include "ephy-sync-secret.h"
 #include "ephy-sync-service.h"
 #include "clear-data-dialog.h"
 #include "cookies-dialog.h"
@@ -174,7 +175,6 @@ on_sync_login_button_clicked (GtkWidget   *button,
   const gchar *emailUTF8;
   const gchar *passwordUTF8;
   gboolean login_ok;
-  guint error_code = 0;
   gchar *error_message = NULL;
 
   gtk_label_set_markup (GTK_LABEL (dialog->sync_email_details_label), "");
@@ -200,8 +200,10 @@ LOG ("[%d] email: %s", __LINE__, emailUTF8);
 LOG ("[%d] password: %s", __LINE__, passwordUTF8);
 
   sync_service = ephy_shell_get_global_sync_service ();
-  ephy_sync_service_stretch (sync_service, emailUTF8, passwordUTF8);
-  login_ok = ephy_sync_service_login (sync_service, &error_code, &error_message);
+  login_ok = ephy_sync_service_login (sync_service,
+                                      emailUTF8,
+                                      passwordUTF8,
+                                      &error_message);
 
   if (login_ok == FALSE) {
     /* Translators: the %s refers to the error message. */
@@ -230,10 +232,17 @@ static void
 on_sync_logout_button_clicked (GtkWidget   *button,
                                PrefsDialog *dialog)
 {
+  EphySyncService *sync_service;
+
+  sync_service = ephy_shell_get_global_sync_service ();
+
   gtk_entry_set_text (GTK_ENTRY (dialog->sync_email_entry), "");
   gtk_entry_set_text (GTK_ENTRY (dialog->sync_password_entry), "");
 
-  /* TODO: Call /session/destroy endpoint and forget tokens */
+  /* TODO: Call session/destroy endpoint */
+
+  ephy_sync_service_delete_all_tokens (sync_service);
+  ephy_sync_secret_forget_all_tokens ();
 
   g_settings_set_string (EPHY_SETTINGS_MAIN,
                          EPHY_PREFS_SYNC_USER,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]