[epiphany/wip/sync: 2/3] sync: Rename and reorder some functions



commit 20893788d9a9b5a0c3bb30ca321d632264e70cc6
Author: Gabriel Ivascu <ivascu gabriel59 gmail com>
Date:   Mon Jun 12 18:05:49 2017 +0300

    sync: Rename and reorder some functions

 lib/sync/README                  |   15 +-
 lib/sync/debug/ephy-sync-debug.c |   33 +-
 lib/sync/ephy-sync-crypto.c      | 1307 +++++++++++++++++++-------------------
 lib/sync/ephy-sync-crypto.h      |  102 ++--
 lib/sync/ephy-sync-service.c     |  450 +++++++-------
 lib/sync/ephy-sync-service.h     |   32 +-
 src/prefs-dialog.c               |   16 +-
 7 files changed, 967 insertions(+), 988 deletions(-)
---
diff --git a/lib/sync/README b/lib/sync/README
index 08117fd..95f7353 100644
--- a/lib/sync/README
+++ b/lib/sync/README
@@ -393,16 +393,17 @@
   EphySyncCrypto is a helper module that handles all the cryptographic stuff.
   Its API include:
 
-    * _process_session_token(). Derives the Hawk id and key from a sessionToken.
+    * _derive_session_token(). Derives the Hawk id and key from a sessionToken.
 
-    * _process_key_fetch_token(). Derives the Hawk id and key, the response HMAC
+    * _derive_key_fetch_token(). Derives the Hawk id and key, the response HMAC
       key and the response XOR key from a keyFetchToken.
 
-    * _compute_sync_keys(). Derives the Master Sync Key from the unwrapBKey
+    * _derive_master_keys(). Derives the Master Sync Key from the unwrapBKey
       token, the bundle returned by the /accounts/keys endpoint of the Firefox
-      Accounts Server, the response HMAC key and the response XOR key.
+      Accounts Server, the response HMAC key and the response XOR key. kB is
+      the Master Sync Key and kA is left unused.
 
-    * _derive_key_bundle(). Derives the key bundle from the Master Sync Key.
+    * _derive_master_bundle(). Derives the key bundle from the Master Sync Key.
 
     * _generate_crypto_keys(). Generates a new crypto/keys record.
 
@@ -410,13 +411,13 @@
 
     * _decrypt_record(). Decrypts a BSO payload into a clear text.
 
-    * _generate_rsa_key_pair(). Generates a RSA key pair. This is needed when
+    * _rsa_key_pair_new(). Generates a RSA key pair. This is needed when
       obtaining an identify certificate and creating the BrowserID assertion.
 
     * _create_assertion(). Creates a BrowserID assertion from a certificate, an
       audience and a RSA key pair.
 
-    * _compute_hawk_header(). Creates a Hawk header that is used to authorize
+    * _hawk_header_new(). Creates a Hawk header that is used to authorize
       Hawk requests. Unfortunately, there isn't any C library for creating Hawk
       headers so the code has been reproduced from a Python library [19].
 
diff --git a/lib/sync/debug/ephy-sync-debug.c b/lib/sync/debug/ephy-sync-debug.c
index efd49c5..a19093f 100644
--- a/lib/sync/debug/ephy-sync-debug.c
+++ b/lib/sync/debug/ephy-sync-debug.c
@@ -114,7 +114,7 @@ ephy_sync_debug_get_bundle_for_collection (const char *collection)
   array = json_object_has_member (collections, collection) ?
           json_object_get_array_member (collections, collection) :
           json_object_get_array_member (json, "default");
-  bundle = ephy_sync_crypto_key_bundle_from_array (array);
+  bundle = ephy_sync_crypto_key_bundle_new (array);
 
   json_node_unref (node);
 free_secrets:
@@ -216,9 +216,8 @@ ephy_sync_debug_prepare_soup_message (const char   *url,
   if (!g_strcmp0 (method, "PUT") || !g_strcmp0(method, "POST"))
     soup_message_headers_append (msg->request_headers, "content-type", content_type);
 
-  header = ephy_sync_crypto_compute_hawk_header (url, method, hawk_id,
-                                                 hawk_key, hawk_key_len,
-                                                 options);
+  header = ephy_sync_crypto_hawk_header_new (url, method, hawk_id,
+                                             hawk_key, hawk_key_len, options);
   soup_message_headers_append (msg->request_headers, "authorization", header->header);
 
   ephy_sync_crypto_hawk_header_free (header);
@@ -254,7 +253,7 @@ ephy_sync_debug_get_signed_certificate (const char           *session_token,
   g_assert (session_token);
   g_assert (keypair);
 
-  ephy_sync_crypto_process_session_token (session_token, &id, &key, &tmp, 32);
+  ephy_sync_crypto_derive_session_token (session_token, &id, &key, &tmp);
   id_hex = ephy_sync_utils_encode_hex (id, 32);
   n = mpz_get_str (NULL, 10, keypair->public.n);
   e = mpz_get_str (NULL, 10, keypair->public.e);
@@ -324,10 +323,10 @@ ephy_sync_debug_get_storage_credentials (char **storage_endpoint,
   char *certificate;
   char *audience;
   char *assertion;
-  char *hashed_key_b;
+  char *hashed_kb;
   char *client_state;
   char *authorization;
-  guint8 *key_b;
+  guint8 *kb;
   const char *session_token;
   guint status_code;
   gboolean success = FALSE;
@@ -336,7 +335,7 @@ ephy_sync_debug_get_storage_credentials (char **storage_endpoint,
   if (!secrets)
     return FALSE;
 
-  keypair = ephy_sync_crypto_generate_rsa_key_pair ();
+  keypair = ephy_sync_crypto_rsa_key_pair_new ();
   session_token = json_object_get_string_member (secrets, "session_token");
   certificate = ephy_sync_debug_get_signed_certificate (session_token, keypair);
   if (!certificate)
@@ -344,9 +343,9 @@ ephy_sync_debug_get_storage_credentials (char **storage_endpoint,
 
   audience = ephy_sync_utils_get_audience (TOKEN_SERVER_URL);
   assertion = ephy_sync_crypto_create_assertion (certificate, audience, 300, keypair);
-  key_b = ephy_sync_utils_decode_hex (json_object_get_string_member (secrets, "master_key"));
-  hashed_key_b = g_compute_checksum_for_data (G_CHECKSUM_SHA256, key_b, 32);
-  client_state = g_strndup (hashed_key_b, 32);
+  kb = ephy_sync_utils_decode_hex (json_object_get_string_member (secrets, "master_key"));
+  hashed_kb = g_compute_checksum_for_data (G_CHECKSUM_SHA256, kb, 32);
+  client_state = g_strndup (hashed_kb, 32);
   authorization = g_strdup_printf ("BrowserID %s", assertion);
   msg = soup_message_new ("GET", TOKEN_SERVER_URL);
   soup_message_headers_append (msg->request_headers, "X-Client-State", client_state);
@@ -378,8 +377,8 @@ free_session:
   g_object_unref (msg);
   g_free (authorization);
   g_free (client_state);
-  g_free (hashed_key_b);
-  g_free (key_b);
+  g_free (hashed_kb);
+  g_free (kb);
   g_free (assertion);
   g_free (audience);
   g_free (certificate);
@@ -902,7 +901,7 @@ ephy_sync_debug_view_crypto_keys_record (void)
   char *crypto_keys;
   const char *payload;
   const char *key_b_hex;
-  guint8 *key_b;
+  guint8 *kb;
 
   secrets = ephy_sync_debug_load_secrets ();
   if (!secrets)
@@ -922,8 +921,8 @@ ephy_sync_debug_view_crypto_keys_record (void)
   json = json_node_get_object (node);
   payload = json_object_get_string_member (json, "payload");
   key_b_hex = json_object_get_string_member (secrets, "master_key");
-  key_b = ephy_sync_utils_decode_hex (key_b_hex);
-  bundle = ephy_sync_crypto_derive_key_bundle (key_b, 32);
+  kb = ephy_sync_utils_decode_hex (key_b_hex);
+  bundle = ephy_sync_crypto_derive_master_bundle (kb);
   crypto_keys = ephy_sync_crypto_decrypt_record (payload, bundle);
 
   if (!crypto_keys)
@@ -934,7 +933,7 @@ ephy_sync_debug_view_crypto_keys_record (void)
   g_free (crypto_keys);
 free_bundle:
   ephy_sync_crypto_key_bundle_free (bundle);
-  g_free (key_b);
+  g_free (kb);
   json_node_unref (node);
 free_response:
   g_free (response);
diff --git a/lib/sync/ephy-sync-crypto.c b/lib/sync/ephy-sync-crypto.c
index d7b6a33..e18784c 100644
--- a/lib/sync/ephy-sync-crypto.c
+++ b/lib/sync/ephy-sync-crypto.c
@@ -127,148 +127,6 @@ ephy_sync_crypto_hawk_artifacts_free (SyncCryptoHawkArtifacts *artifacts)
   g_slice_free (SyncCryptoHawkArtifacts, artifacts);
 }
 
-static SyncCryptoHawkHeader *
-ephy_sync_crypto_hawk_header_new (const char              *header,
-                                  SyncCryptoHawkArtifacts *artifacts)
-{
-  SyncCryptoHawkHeader *hawk_header;
-
-  hawk_header = g_slice_new (SyncCryptoHawkHeader);
-  hawk_header->header = g_strdup (header);
-  hawk_header->artifacts = artifacts;
-
-  return hawk_header;
-}
-
-void
-ephy_sync_crypto_hawk_header_free (SyncCryptoHawkHeader *hawk_header)
-{
-  g_return_if_fail (hawk_header);
-
-  g_free (hawk_header->header);
-  ephy_sync_crypto_hawk_artifacts_free (hawk_header->artifacts);
-
-  g_slice_free (SyncCryptoHawkHeader, hawk_header);
-}
-
-static SyncCryptoRSAKeyPair *
-ephy_sync_crypto_rsa_key_pair_new (struct rsa_public_key  public,
-                                   struct rsa_private_key private)
-{
-  SyncCryptoRSAKeyPair *rsa_key_pair;
-
-  rsa_key_pair = g_slice_new (SyncCryptoRSAKeyPair);
-  rsa_key_pair->public = public;
-  rsa_key_pair->private = private;
-
-  return rsa_key_pair;
-}
-
-void
-ephy_sync_crypto_rsa_key_pair_free (SyncCryptoRSAKeyPair *rsa_key_pair)
-{
-  g_return_if_fail (rsa_key_pair);
-
-  rsa_public_key_clear (&rsa_key_pair->public);
-  rsa_private_key_clear (&rsa_key_pair->private);
-
-  g_slice_free (SyncCryptoRSAKeyPair, rsa_key_pair);
-}
-
-static SyncCryptoKeyBundle *
-ephy_sync_crypto_key_bundle_new (const char *aes_key_hex,
-                                 const char *hmac_key_hex)
-{
-  SyncCryptoKeyBundle *bundle;
-
-  bundle = g_slice_new (SyncCryptoKeyBundle);
-  bundle->aes_key_hex = g_strdup (aes_key_hex);
-  bundle->hmac_key_hex = g_strdup (hmac_key_hex);
-
-  return bundle;
-}
-
-SyncCryptoKeyBundle *
-ephy_sync_crypto_key_bundle_from_array (JsonArray *array)
-{
-  SyncCryptoKeyBundle *bundle;
-  char *aes_key_hex;
-  char *hmac_key_hex;
-  guint8 *aes_key;
-  guint8 *hmac_key;
-  gsize len;
-
-  g_return_val_if_fail (array, NULL);
-  g_return_val_if_fail (json_array_get_length (array) == 2, NULL);
-
-  aes_key = g_base64_decode (json_array_get_string_element (array, 0), &len);
-  hmac_key = g_base64_decode (json_array_get_string_element (array, 1), &len);
-  aes_key_hex = ephy_sync_utils_encode_hex (aes_key, 32);
-  hmac_key_hex = ephy_sync_utils_encode_hex (hmac_key, 32);
-  bundle = ephy_sync_crypto_key_bundle_new (aes_key_hex, hmac_key_hex);
-
-  g_free (aes_key);
-  g_free (hmac_key);
-  g_free (aes_key_hex);
-  g_free (hmac_key_hex);
-
-  return bundle;
-}
-
-void
-ephy_sync_crypto_key_bundle_free (SyncCryptoKeyBundle *bundle)
-{
-  g_return_if_fail (bundle);
-
-  g_free (bundle->aes_key_hex);
-  g_free (bundle->hmac_key_hex);
-
-  g_slice_free (SyncCryptoKeyBundle, bundle);
-}
-
-static char *
-ephy_sync_crypto_kw (const char *name)
-{
-  g_assert (name);
-
-  /* Concatenate the given name to the Mozilla prefix.
-   * See https://raw.githubusercontent.com/wiki/mozilla/fxa-auth-server/images/onepw-create.png
-   */
-  return g_strconcat ("identity.mozilla.com/picl/v1/", name, NULL);
-}
-
-static guint8 *
-ephy_sync_crypto_xor (const guint8 *a,
-                      const guint8 *b,
-                      gsize         length)
-{
-  guint8 *xored;
-
-  g_assert (a);
-  g_assert (b);
-
-  xored = g_malloc (length);
-  for (gsize i = 0; i < length; i++)
-    xored[i] = a[i] ^ b[i];
-
-  return xored;
-}
-
-static gboolean
-ephy_sync_crypto_equals (const guint8 *a,
-                         const guint8 *b,
-                         gsize         length)
-{
-  g_assert (a);
-  g_assert (b);
-
-  for (gsize i = 0; i < length; i++)
-    if (a[i] != b[i])
-      return FALSE;
-
-  return TRUE;
-}
-
 static char *
 ephy_sync_crypto_find_and_replace (const char *where,
                                    const char *to_find,
@@ -307,8 +165,71 @@ ephy_sync_crypto_find_and_replace (const char *where,
 }
 
 static char *
-ephy_sync_crypto_normalize_string (const char              *type,
-                                   SyncCryptoHawkArtifacts *artifacts)
+hawk_parse_content_type (const char *content_type)
+{
+  char **tokens;
+  char *retval;
+
+  g_assert (content_type);
+
+  tokens = g_strsplit (content_type, ";", -1);
+  retval = g_ascii_strdown (g_strstrip (tokens[0]), -1);
+  g_strfreev (tokens);
+
+  return retval;
+}
+
+static char *
+hawk_compute_payload_hash (const char *payload,
+                           const char *content_type)
+{
+  guint8 *digest;
+  char *digest_hex;
+  char *content;
+  char *update;
+  char *hash;
+
+  g_assert (payload);
+  g_assert (content_type);
+
+  content = hawk_parse_content_type (content_type);
+  update = g_strdup_printf ("hawk.%d.payload\n%s\n%s\n",
+                            HAWK_VERSION, content, payload);
+
+  digest_hex = g_compute_checksum_for_string (G_CHECKSUM_SHA256, update, -1);
+  digest = ephy_sync_utils_decode_hex (digest_hex);
+  hash = g_base64_encode (digest, g_checksum_type_get_length (G_CHECKSUM_SHA256));
+
+  g_free (content);
+  g_free (update);
+  g_free (digest_hex);
+  g_free (digest);
+
+  return hash;
+}
+
+static char *
+hawk_append_to_header (char       *header,
+                       const char *name,
+                       const char *value)
+{
+  char *new_header;
+  char *tmp;
+
+  g_assert (header);
+  g_assert (name);
+  g_assert (value);
+
+  tmp = header;
+  new_header = g_strconcat (header, ", ", name, "=\"", value, "\"", NULL);
+  g_free (tmp);
+
+  return new_header;
+}
+
+static char *
+hawk_normalize_string (const char              *type,
+                       SyncCryptoHawkArtifacts *artifacts)
 {
   char *host;
   char *info;
@@ -355,54 +276,10 @@ ephy_sync_crypto_normalize_string (const char              *type,
 }
 
 static char *
-ephy_sync_crypto_parse_content_type (const char *content_type)
-{
-  char **tokens;
-  char *retval;
-
-  g_assert (content_type);
-
-  tokens = g_strsplit (content_type, ";", -1);
-  retval = g_ascii_strdown (g_strstrip (tokens[0]), -1);
-  g_strfreev (tokens);
-
-  return retval;
-}
-
-static char *
-ephy_sync_crypto_calculate_payload_hash (const char *payload,
-                                         const char *content_type)
-{
-  guint8 *digest;
-  char *digest_hex;
-  char *content;
-  char *update;
-  char *hash;
-
-  g_assert (payload);
-  g_assert (content_type);
-
-  content = ephy_sync_crypto_parse_content_type (content_type);
-  update = g_strdup_printf ("hawk.%d.payload\n%s\n%s\n",
-                            HAWK_VERSION, content, payload);
-
-  digest_hex = g_compute_checksum_for_string (G_CHECKSUM_SHA256, update, -1);
-  digest = ephy_sync_utils_decode_hex (digest_hex);
-  hash = g_base64_encode (digest, g_checksum_type_get_length (G_CHECKSUM_SHA256));
-
-  g_free (content);
-  g_free (update);
-  g_free (digest_hex);
-  g_free (digest);
-
-  return hash;
-}
-
-static char *
-ephy_sync_crypto_calculate_mac (const char              *type,
-                                const guint8            *key,
-                                gsize                    key_len,
-                                SyncCryptoHawkArtifacts *artifacts)
+hawk_compute_mac (const char              *type,
+                  const guint8            *key,
+                  gsize                    key_len,
+                  SyncCryptoHawkArtifacts *artifacts)
 {
   guint8 *digest;
   char *digest_hex;
@@ -414,7 +291,7 @@ ephy_sync_crypto_calculate_mac (const char              *type,
   g_assert (artifacts);
 
   /* Serialize the mac type and artifacts into a HAWK string. */
-  normalized = ephy_sync_crypto_normalize_string (type, artifacts);
+  normalized = hawk_normalize_string (type, artifacts);
   digest_hex = g_compute_hmac_for_string (G_CHECKSUM_SHA256,
                                           key, key_len,
                                           normalized, -1);
@@ -428,28 +305,234 @@ ephy_sync_crypto_calculate_mac (const char              *type,
   return mac;
 }
 
-static char *
-ephy_sync_crypto_append_to_header (char       *header,
-                                   const char *name,
-                                   const char *value)
+SyncCryptoHawkHeader *
+ephy_sync_crypto_hawk_header_new (const char            *url,
+                                  const char            *method,
+                                  const char            *id,
+                                  const guint8          *key,
+                                  gsize                  key_len,
+                                  SyncCryptoHawkOptions *options)
 {
-  char *new_header;
-  char *tmp;
+  SyncCryptoHawkHeader *hawk_header;
+  SyncCryptoHawkArtifacts *artifacts;
+  SoupURI *uri;
+  char *resource;
+  char *hash;
+  char *header;
+  char *mac;
+  char *nonce;
+  char *payload;
+  char *timestamp;
+  guint8 *bytes;
+  gint64 ts;
 
-  g_assert (header);
-  g_assert (name);
-  g_assert (value);
+  g_return_val_if_fail (url, NULL);
+  g_return_val_if_fail (method, NULL);
+  g_return_val_if_fail (id, NULL);
+  g_return_val_if_fail (key, NULL);
 
-  tmp = header;
-  new_header = g_strconcat (header, ", ", name, "=\"", value, "\"", NULL);
-  g_free (tmp);
+  ts = g_get_real_time () / 1000000;
+  hash = options ? g_strdup (options->hash) : NULL;
+  payload = options ? options->payload : NULL;
+  timestamp = options ? options->timestamp : NULL;
+  uri = soup_uri_new (url);
+  resource = !soup_uri_get_query (uri) ? g_strdup (soup_uri_get_path (uri))
+                                       : g_strconcat (soup_uri_get_path (uri),
+                                                      "?",
+                                                      soup_uri_get_query (uri),
+                                                      NULL);
 
-  return new_header;
+  if (options && options->nonce) {
+    nonce = g_strdup (options->nonce);
+  } else {
+    bytes = g_malloc (NONCE_LEN / 2);
+    ephy_sync_utils_generate_random_bytes (NULL, NONCE_LEN / 2, bytes);
+    nonce = ephy_sync_utils_encode_hex (bytes, NONCE_LEN / 2);
+    g_free (bytes);
+  }
+
+  if (timestamp) {
+    char *local_time_offset;
+    gint64 offset;
+
+    local_time_offset = options ? options->local_time_offset : NULL;
+    offset = local_time_offset ? g_ascii_strtoll (local_time_offset, NULL, 10) : 0;
+    ts = g_ascii_strtoll (timestamp, NULL, 10) + offset;
+  }
+
+  if (!hash && payload) {
+    const char *content_type = options ? options->content_type : "text/plain";
+
+    /* Calculate hash for the given payload. */
+    hash = hawk_compute_payload_hash (payload, content_type);
+  }
+
+  /* Create artifacts from options. */
+  artifacts = ephy_sync_crypto_hawk_artifacts_new (options ? options->app : NULL,
+                                                   options ? options->dlg : NULL,
+                                                   options ? options->ext : NULL,
+                                                   hash,
+                                                   soup_uri_get_host (uri),
+                                                   method,
+                                                   nonce,
+                                                   soup_uri_get_port (uri),
+                                                   resource,
+                                                   ts);
+
+  header = g_strconcat ("Hawk id=\"", id, "\"",
+                        ", ts=\"", artifacts->ts, "\"",
+                        ", nonce=\"", artifacts->nonce, "\"",
+                        NULL);
+
+  /* Append pre-calculated payload hash if any. */
+  if (artifacts->hash && strlen (artifacts->hash) > 0)
+    header = hawk_append_to_header (header, "hash", artifacts->hash);
+
+  /* Append the application specific data if any. */
+  if (artifacts->ext && strlen (artifacts->ext) > 0) {
+    char *h_ext;
+    char *tmp_ext;
+
+    tmp_ext = ephy_sync_crypto_find_and_replace (artifacts->ext, "\\", "\\\\");
+    h_ext = ephy_sync_crypto_find_and_replace (tmp_ext, "\n", "\\n");
+    header = hawk_append_to_header (header, "ext", h_ext);
+
+    g_free (h_ext);
+    g_free (tmp_ext);
+  }
+
+  /* Calculate and append a message authentication code (MAC). */
+  mac = hawk_compute_mac ("header", key, key_len, artifacts);
+  header = hawk_append_to_header (header, "mac", mac);
+
+  /* Append the Oz application id if any. */
+  if (artifacts->app) {
+    header = hawk_append_to_header (header, "app", artifacts->app);
+
+    /* Append the Oz delegated-by application id if any. */
+    if (artifacts->dlg)
+      header = hawk_append_to_header (header, "dlg", artifacts->dlg);
+  }
+
+  hawk_header = g_slice_new (SyncCryptoHawkHeader);
+  hawk_header->header = g_strdup (header);
+  hawk_header->artifacts = artifacts;
+
+  soup_uri_free (uri);
+  g_free (hash);
+  g_free (mac);
+  g_free (nonce);
+  g_free (resource);
+  g_free (header);
+
+  return hawk_header;
+}
+
+void
+ephy_sync_crypto_hawk_header_free (SyncCryptoHawkHeader *header)
+{
+  g_return_if_fail (header);
+
+  g_free (header->header);
+  ephy_sync_crypto_hawk_artifacts_free (header->artifacts);
+
+  g_slice_free (SyncCryptoHawkHeader, header);
+}
+
+SyncCryptoRSAKeyPair *
+ephy_sync_crypto_rsa_key_pair_new (void)
+{
+  SyncCryptoRSAKeyPair *key_pair;
+  struct rsa_public_key public;
+  struct rsa_private_key private;
+  int success;
+
+  rsa_public_key_init (&public);
+  rsa_private_key_init (&private);
+
+  /* The public exponent, usually one of the small Fermat primes 3, 5, 17, 257, 65537. */
+  mpz_set_ui (public.e, 65537);
+
+  /* Key sizes below 2048 are considered breakable and should not be used. */
+  success = rsa_generate_keypair (&public, &private,
+                                  NULL, ephy_sync_utils_generate_random_bytes,
+                                  NULL, NULL, 2048, 0);
+  /* Given correct parameters, this never fails. */
+  g_assert (success);
+
+  key_pair = g_slice_new (SyncCryptoRSAKeyPair);
+  key_pair->public = public;
+  key_pair->private = private;
+
+  return key_pair;
+}
+
+void
+ephy_sync_crypto_rsa_key_pair_free (SyncCryptoRSAKeyPair *key_pair)
+{
+  g_return_if_fail (key_pair);
+
+  rsa_public_key_clear (&key_pair->public);
+  rsa_private_key_clear (&key_pair->private);
+
+  g_slice_free (SyncCryptoRSAKeyPair, key_pair);
+}
+
+SyncCryptoKeyBundle *
+ephy_sync_crypto_key_bundle_new (JsonArray *array)
+{
+  SyncCryptoKeyBundle *bundle;
+  char *aes_key_hex;
+  char *hmac_key_hex;
+  guint8 *aes_key;
+  guint8 *hmac_key;
+  gsize len;
+
+  g_return_val_if_fail (array, NULL);
+  g_return_val_if_fail (json_array_get_length (array) == 2, NULL);
+
+  aes_key = g_base64_decode (json_array_get_string_element (array, 0), &len);
+  hmac_key = g_base64_decode (json_array_get_string_element (array, 1), &len);
+  aes_key_hex = ephy_sync_utils_encode_hex (aes_key, 32);
+  hmac_key_hex = ephy_sync_utils_encode_hex (hmac_key, 32);
+
+  bundle = g_slice_new (SyncCryptoKeyBundle);
+  bundle->aes_key_hex = g_strdup (aes_key_hex);
+  bundle->hmac_key_hex = g_strdup (hmac_key_hex);
+
+  g_free (aes_key);
+  g_free (hmac_key);
+  g_free (aes_key_hex);
+  g_free (hmac_key_hex);
+
+  return bundle;
+}
+
+void
+ephy_sync_crypto_key_bundle_free (SyncCryptoKeyBundle *bundle)
+{
+  g_return_if_fail (bundle);
+
+  g_free (bundle->aes_key_hex);
+  g_free (bundle->hmac_key_hex);
+
+  g_slice_free (SyncCryptoKeyBundle, bundle);
+}
+
+static char *
+ephy_sync_crypto_kw (const char *name)
+{
+  g_assert (name);
+
+  /* Concatenate the given name to the Mozilla prefix.
+   * See https://raw.githubusercontent.com/wiki/mozilla/fxa-auth-server/images/onepw-create.png
+   */
+  return g_strconcat ("identity.mozilla.com/picl/v1/", name, NULL);
 }
 
 static guint8 *
 ephy_sync_crypto_concat_bytes (const guint8 *bytes,
-                               gsize         bytes_len,
+                               gsize         len,
                                ...)
 {
   va_list args;
@@ -458,11 +541,11 @@ ephy_sync_crypto_concat_bytes (const guint8 *bytes,
   gsize next_len;
   gsize out_len;
 
-  out_len = bytes_len;
+  out_len = len;
   out = g_malloc (out_len);
   memcpy (out, bytes, out_len);
 
-  va_start (args, bytes_len);
+  va_start (args, len);
   while ((next = va_arg (args, guint8 *)) != NULL) {
     next_len = va_arg (args, gsize);
     out = g_realloc (out, out_len + next_len);
@@ -504,7 +587,8 @@ ephy_sync_crypto_hkdf (const guint8 *in,
   g_assert (out_len <= hash_len * 255);
 
   /* Implementation of the HMAC-based Extract-and-Expand Key Derivation Function.
-   * See https://tools.ietf.org/html/rfc5869 */
+   * See https://tools.ietf.org/html/rfc5869
+   */
 
   /* If salt value was not provided, use an array of hash_len zeros. */
   if (!salt) {
@@ -554,136 +638,50 @@ ephy_sync_crypto_hkdf (const guint8 *in,
   g_free (out_full);
 }
 
-static guint8 *
-ephy_sync_crypto_pad (const char *text,
-                      gsize       block_len,
-                      gsize      *out_len)
+void
+ephy_sync_crypto_derive_session_token (const char  *session_token,
+                                       guint8     **token_id,
+                                       guint8     **req_hmac_key,
+                                       guint8     **request_key)
 {
+  guint8 *token;
   guint8 *out;
-  gsize text_len = strlen (text);
-
-  g_assert (text);
-  g_assert (out_len);
-
-  if (text_len % block_len == 0)
-    *out_len = text_len;
-  else
-    *out_len = text_len + block_len - text_len % block_len;
-
-  out = g_malloc (*out_len);
-
-  if (text_len % block_len != 0)
-    memset (out, block_len - text_len % block_len, *out_len);
-
-  memcpy (out, text, text_len);
-
-  return out;
-}
-
-static guint8 *
-ephy_sync_crypto_aes_256_encrypt (const char   *text,
-                                  const guint8 *key,
-                                  const guint8 *iv,
-                                  gsize        *out_len)
-{
-  guint8 *padded;
-  guint8 *encrypted;
-  gsize padded_len;
-  struct CBC_CTX(struct aes256_ctx, AES_BLOCK_SIZE) ctx;
-
-  g_assert (text);
-  g_assert (key);
-  g_assert (iv);
-  g_assert (out_len);
-
-  padded = ephy_sync_crypto_pad (text, AES_BLOCK_SIZE, &padded_len);
-  encrypted = g_malloc (padded_len);
-
-  aes256_set_encrypt_key(&ctx.ctx, key);
-  CBC_SET_IV(&ctx, iv);
-  CBC_ENCRYPT(&ctx, aes256_encrypt, padded_len, encrypted, padded);
-
-  *out_len = padded_len;
-  g_free (padded);
-
-  return encrypted;
-}
-
-static char *
-ephy_sync_crypto_unpad (const guint8 *data,
-                        gsize         data_len,
-                        gsize         block_len)
-{
-  char *out;
-  gsize out_len;
-  gsize padding = data[data_len - 1];
-
-  g_assert (data);
-
-  if (padding >= 1 && padding <= block_len)
-    out_len = data_len - padding;
-  else
-    out_len = data_len;
-
-  out = g_malloc0 (out_len + 1);
-  memcpy (out, data, out_len);
-
-  return out;
-}
-
-static char *
-ephy_sync_crypto_aes_256_decrypt (const guint8 *data,
-                                  gsize         data_len,
-                                  const guint8 *key,
-                                  const guint8 *iv)
-{
-  guint8 *decrypted;
-  char *unpadded;
-  struct CBC_CTX(struct aes256_ctx, AES_BLOCK_SIZE) ctx;
-
-  g_assert (data);
-  g_assert (key);
-  g_assert (iv);
-
-  decrypted = g_malloc (data_len);
-
-  aes256_set_decrypt_key (&ctx.ctx, key);
-  CBC_SET_IV (&ctx, iv);
-  CBC_DECRYPT (&ctx, aes256_decrypt, data_len, decrypted, data);
-
-  unpadded = ephy_sync_crypto_unpad (decrypted, data_len, AES_BLOCK_SIZE);
-  g_free (decrypted);
+  char *info;
+  gsize len = 32; /* sessionToken is always 32 bytes. */
 
-  return unpadded;
-}
+  g_return_if_fail (session_token);
+  g_return_if_fail (token_id);
+  g_return_if_fail (req_hmac_key);
+  g_return_if_fail (request_key);
 
-static gboolean
-ephy_sync_crypto_hmac_is_valid (const char   *text,
-                                const guint8 *key,
-                                const char   *expected)
-{
-  char *hmac;
-  gboolean retval;
+  token = ephy_sync_utils_decode_hex (session_token);
+  info = ephy_sync_crypto_kw ("sessionToken");
+  out = g_malloc (3 * len);
 
-  g_assert (text);
-  g_assert (key);
-  g_assert (expected);
+  /* Use the sessionToken to derive tokenID, reqHMACkey and requestKey. */
+  ephy_sync_crypto_hkdf (token, len,
+                         NULL, 0,
+                         (guint8 *)info, strlen (info),
+                         out, 3 * len);
 
-  /* SHA256 expects a 32 bytes key. */
-  hmac = g_compute_hmac_for_string (G_CHECKSUM_SHA256, key, 32, text, -1);
-  retval = g_strcmp0 (hmac, expected) == 0;
-  g_free (hmac);
+  *token_id = g_malloc (len);
+  *req_hmac_key = g_malloc (len);
+  *request_key = g_malloc (len);
+  memcpy (*token_id, out, len);
+  memcpy (*req_hmac_key, out + len, len);
+  memcpy (*request_key, out + 2 * len, len);
 
-  return retval;
+  g_free (token);
+  g_free (out);
+  g_free (info);
 }
 
 void
-ephy_sync_crypto_process_key_fetch_token (const char  *key_fetch_token,
-                                          guint8     **token_id,
-                                          guint8     **req_hmac_key,
-                                          guint8     **resp_hmac_key,
-                                          guint8     **resp_xor_key,
-                                          gsize        token_len)
+ephy_sync_crypto_derive_key_fetch_token (const char  *key_fetch_token,
+                                         guint8     **token_id,
+                                         guint8     **req_hmac_key,
+                                         guint8     **resp_hmac_key,
+                                         guint8     **resp_xor_key)
 {
   guint8 *kft;
   guint8 *out1;
@@ -691,6 +689,7 @@ ephy_sync_crypto_process_key_fetch_token (const char  *key_fetch_token,
   guint8 *key_request_key;
   char *info_kft;
   char *info_keys;
+  gsize len = 32; /* keyFetchToken is always 32 bytes. */
 
   g_return_if_fail (key_fetch_token);
   g_return_if_fail (token_id);
@@ -701,32 +700,32 @@ ephy_sync_crypto_process_key_fetch_token (const char  *key_fetch_token,
   kft = ephy_sync_utils_decode_hex (key_fetch_token);
   info_kft = ephy_sync_crypto_kw ("keyFetchToken");
   info_keys = ephy_sync_crypto_kw ("account/keys");
-  out1 = g_malloc (3 * token_len);
-  out2 = g_malloc (3 * token_len);
+  out1 = g_malloc (3 * len);
+  out2 = g_malloc (3 * len);
 
   /* Use the keyFetchToken to derive tokenID, reqHMACkey and keyRequestKey. */
-  ephy_sync_crypto_hkdf (kft, token_len,
+  ephy_sync_crypto_hkdf (kft, len,
                          NULL, 0,
                          (guint8 *)info_kft, strlen (info_kft),
-                         out1, 3 * token_len);
+                         out1, 3 * len);
 
-  *token_id = g_malloc (token_len);
-  *req_hmac_key = g_malloc (token_len);
-  key_request_key = g_malloc (token_len);
-  memcpy (*token_id, out1, token_len);
-  memcpy (*req_hmac_key, out1 + token_len, token_len);
-  memcpy (key_request_key, out1 + 2 * token_len, token_len);
+  *token_id = g_malloc (len);
+  *req_hmac_key = g_malloc (len);
+  key_request_key = g_malloc (len);
+  memcpy (*token_id, out1, len);
+  memcpy (*req_hmac_key, out1 + len, len);
+  memcpy (key_request_key, out1 + 2 * len, len);
 
   /* Use the keyRequestKey to derive respHMACkey and respXORkey. */
-  ephy_sync_crypto_hkdf (key_request_key, token_len,
+  ephy_sync_crypto_hkdf (key_request_key, len,
                          NULL, 0,
                          (guint8 *)info_keys, strlen (info_keys),
-                         out2, 3 * token_len);
+                         out2, 3 * len);
 
-  *resp_hmac_key = g_malloc (token_len);
-  *resp_xor_key = g_malloc (2 * token_len);
-  memcpy (*resp_hmac_key, out2, token_len);
-  memcpy (*resp_xor_key, out2 + token_len, 2 * token_len);
+  *resp_hmac_key = g_malloc (len);
+  *resp_xor_key = g_malloc (2 * len);
+  memcpy (*resp_hmac_key, out2, len);
+  memcpy (*resp_xor_key, out2 + len, 2 * len);
 
   g_free (kft);
   g_free (out1);
@@ -736,97 +735,92 @@ ephy_sync_crypto_process_key_fetch_token (const char  *key_fetch_token,
   g_free (key_request_key);
 }
 
-void
-ephy_sync_crypto_process_session_token (const char  *session_token,
-                                        guint8     **token_id,
-                                        guint8     **req_hmac_key,
-                                        guint8     **request_key,
-                                        gsize        token_len)
+static guint8 *
+ephy_sync_crypto_xor_bytes (const guint8 *a,
+                            const guint8 *b,
+                            gsize         len)
 {
-  guint8 *st;
-  guint8 *out;
-  char *info;
+  guint8 *xored;
 
-  g_return_if_fail (session_token);
-  g_return_if_fail (token_id);
-  g_return_if_fail (req_hmac_key);
-  g_return_if_fail (request_key);
+  g_assert (a);
+  g_assert (b);
 
-  st = ephy_sync_utils_decode_hex (session_token);
-  info = ephy_sync_crypto_kw ("sessionToken");
-  out = g_malloc (3 * token_len);
+  xored = g_malloc (len);
+  for (gsize i = 0; i < len; i++)
+    xored[i] = a[i] ^ b[i];
 
-  /* Use the sessionToken to derive tokenID, reqHMACkey and requestKey. */
-  ephy_sync_crypto_hkdf (st, token_len,
-                         NULL, 0,
-                         (guint8 *)info, strlen (info),
-                         out, 3 * token_len);
+  return xored;
+}
 
-  *token_id = g_malloc (token_len);
-  *req_hmac_key = g_malloc (token_len);
-  *request_key = g_malloc (token_len);
-  memcpy (*token_id, out, token_len);
-  memcpy (*req_hmac_key, out + token_len, token_len);
-  memcpy (*request_key, out + 2 * token_len, token_len);
+static gboolean
+ephy_sync_crypto_compate_bytes (const guint8 *a,
+                                const guint8 *b,
+                                gsize         len)
+{
+  g_assert (a);
+  g_assert (b);
 
-  g_free (st);
-  g_free (out);
-  g_free (info);
+  for (gsize i = 0; i < len; i++)
+    if (a[i] != b[i])
+      return FALSE;
+
+  return TRUE;
 }
 
 gboolean
-ephy_sync_crypto_compute_sync_keys (const char    *bundle_hex,
-                                    const guint8  *resp_hmac_key,
-                                    const guint8  *resp_xor_key,
-                                    const guint8  *unwrap_b_key,
-                                    guint8       **kA,
-                                    guint8       **kB,
-                                    gsize          key_len)
+ephy_sync_crypto_derive_master_keys (const char    *bundle_hex,
+                                     const guint8  *resp_hmac_key,
+                                     const guint8  *resp_xor_key,
+                                     const guint8  *unwrap_kb,
+                                     guint8       **ka,
+                                     guint8       **kb)
 {
   guint8 *bundle;
   guint8 *ciphertext;
   guint8 *resp_hmac;
   guint8 *resp_hmac_2;
   guint8 *xored;
-  guint8 *wrap_key_b;
+  guint8 *wrap_kb;
   char *resp_hmac_2_hex;
   gboolean retval = TRUE;
+  gsize len = 32; /* The master sync keys are always 32 bytes. */
 
   g_return_val_if_fail (bundle_hex, FALSE);
   g_return_val_if_fail (resp_hmac_key, FALSE);
   g_return_val_if_fail (resp_xor_key, FALSE);
-  g_return_val_if_fail (unwrap_b_key, FALSE);
-  g_return_val_if_fail (kA, FALSE);
-  g_return_val_if_fail (kB, FALSE);
+  g_return_val_if_fail (unwrap_kb, FALSE);
+  g_return_val_if_fail (ka, FALSE);
+  g_return_val_if_fail (kb, FALSE);
 
   bundle = ephy_sync_utils_decode_hex (bundle_hex);
-  ciphertext = g_malloc (2 * key_len);
-  resp_hmac = g_malloc (key_len);
+  ciphertext = g_malloc (2 * len);
+  resp_hmac = g_malloc (len);
 
   /* Compute the MAC and compare it to the expected value. */
-  memcpy (ciphertext, bundle, 2 * key_len);
-  memcpy (resp_hmac, bundle + 2 * key_len, key_len);
+  memcpy (ciphertext, bundle, 2 * len);
+  memcpy (resp_hmac, bundle + 2 * len, len);
   resp_hmac_2_hex = g_compute_hmac_for_data (G_CHECKSUM_SHA256,
-                                             resp_hmac_key, key_len,
-                                             ciphertext, 2 * key_len);
+                                             resp_hmac_key, len,
+                                             ciphertext, 2 * len);
   resp_hmac_2 = ephy_sync_utils_decode_hex (resp_hmac_2_hex);
-  if (!ephy_sync_crypto_equals (resp_hmac, resp_hmac_2, key_len)) {
+  if (!ephy_sync_crypto_compate_bytes (resp_hmac, resp_hmac_2, len)) {
     g_warning ("HMAC values differs from the one expected");
     retval = FALSE;
     goto out;
   }
 
-  /* XOR the extracted ciphertext with the respXORkey, then split in into the
-   * separate kA and wrap(kB) values. */
-  xored = ephy_sync_crypto_xor (ciphertext, resp_xor_key, 2 * key_len);
-  *kA = g_malloc (key_len);
-  memcpy (*kA, xored, key_len);
-  wrap_key_b = g_malloc (key_len);
-  memcpy (wrap_key_b, xored + key_len, key_len);
+  /* XOR the extracted ciphertext with the respXORkey, then split into the
+   * separate kA and wrap(kB) values.
+   */
+  xored = ephy_sync_crypto_xor_bytes (ciphertext, resp_xor_key, 2 * len);
+  *ka = g_malloc (len);
+  memcpy (*ka, xored, len);
+  wrap_kb = g_malloc (len);
+  memcpy (wrap_kb, xored + len, len);
   /* XOR wrap(kB) with unwrapBKey to obtain kB. There is no MAC on wrap(kB). */
-  *kB = ephy_sync_crypto_xor (unwrap_b_key, wrap_key_b, key_len);
+  *kb = ephy_sync_crypto_xor_bytes (unwrap_kb, wrap_kb, len);
 
-  g_free (wrap_key_b);
+  g_free (wrap_kb);
   g_free (xored);
 out:
   g_free (resp_hmac_2);
@@ -839,8 +833,7 @@ out:
 }
 
 SyncCryptoKeyBundle *
-ephy_sync_crypto_derive_key_bundle (const guint8 *key,
-                                    gsize         key_len)
+ephy_sync_crypto_derive_master_bundle (const guint8 *key)
 {
   SyncCryptoKeyBundle *bundle;
   guint8 *salt;
@@ -851,34 +844,37 @@ ephy_sync_crypto_derive_key_bundle (const guint8 *key,
   char *aes_key_hex;
   char *hmac_key_hex;
   const char *info = "identity.mozilla.com/picl/v1/oldsync";
+  gsize len = 32; /* kB is always 32 bytes. */
 
   g_return_val_if_fail (key, NULL);
-  g_return_val_if_fail (key_len > 0, NULL);
 
   /* Perform a two step HKDF with an all-zeros salt.
-   * T(1) will represent the AES key, T(2) will represent the HMAC key. */
-
-  salt = g_malloc0 (key_len);
+   * T(1) will represent the AES key, T(2) will represent the HMAC key.
+   */
+  salt = g_malloc0 (len);
   prk_hex = g_compute_hmac_for_data (G_CHECKSUM_SHA256,
-                                     salt, key_len,
-                                     key, key_len);
+                                     salt, len,
+                                     key, len);
   prk = ephy_sync_utils_decode_hex (prk_hex);
   tmp = ephy_sync_crypto_concat_bytes ((guint8 *)info, strlen (info),
                                        "\x01", 1,
                                        NULL);
   aes_key_hex = g_compute_hmac_for_data (G_CHECKSUM_SHA256,
-                                         prk, key_len,
+                                         prk, len,
                                          tmp, strlen (info) + 1);
   aes_key = ephy_sync_utils_decode_hex (aes_key_hex);
   g_free (tmp);
-  tmp = ephy_sync_crypto_concat_bytes (aes_key, key_len,
+  tmp = ephy_sync_crypto_concat_bytes (aes_key, len,
                                        (guint8 *)info, strlen (info),
                                        "\x02", 1,
                                        NULL);
   hmac_key_hex = g_compute_hmac_for_data (G_CHECKSUM_SHA256,
-                                          prk, key_len,
-                                          tmp, key_len + strlen (info) + 1);
-  bundle = ephy_sync_crypto_key_bundle_new (aes_key_hex, hmac_key_hex);
+                                          prk, len,
+                                          tmp, len + strlen (info) + 1);
+
+  bundle = g_slice_new (SyncCryptoKeyBundle);
+  bundle->aes_key_hex = g_strdup (aes_key_hex);
+  bundle->hmac_key_hex = g_strdup (hmac_key_hex);
 
   g_free (hmac_key_hex);
   g_free (tmp);
@@ -891,7 +887,7 @@ ephy_sync_crypto_derive_key_bundle (const guint8 *key,
 }
 
 char *
-ephy_sync_crypto_generate_crypto_keys (gsize key_len)
+ephy_sync_crypto_generate_crypto_keys (void)
 {
   JsonNode *node;
   JsonObject *object;
@@ -901,13 +897,14 @@ ephy_sync_crypto_generate_crypto_keys (gsize key_len)
   char *aes_key_b64;
   char *hmac_key_b64;
   char *payload;
+  gsize len = 32; /* Crypto keys are always 32 bytes. */
 
-  aes_key = g_malloc (key_len);
-  ephy_sync_utils_generate_random_bytes (NULL, key_len, aes_key);
-  aes_key_b64 = g_base64_encode (aes_key, key_len);
-  hmac_key = g_malloc (key_len);
-  ephy_sync_utils_generate_random_bytes (NULL, key_len, hmac_key);
-  hmac_key_b64 = g_base64_encode (hmac_key, key_len);
+  aes_key = g_malloc (len);
+  ephy_sync_utils_generate_random_bytes (NULL, len, aes_key);
+  aes_key_b64 = g_base64_encode (aes_key, len);
+  hmac_key = g_malloc (len);
+  ephy_sync_utils_generate_random_bytes (NULL, len, hmac_key);
+  hmac_key_b64 = g_base64_encode (hmac_key, len);
 
   node = json_node_new (JSON_NODE_OBJECT);
   object = json_object_new ();
@@ -932,73 +929,126 @@ ephy_sync_crypto_generate_crypto_keys (gsize key_len)
 }
 
 char *
-ephy_sync_crypto_decrypt_record (const char          *payload,
-                                 SyncCryptoKeyBundle *bundle)
+ephy_sync_crypto_create_assertion (const char           *certificate,
+                                   const char           *audience,
+                                   guint64               seconds,
+                                   SyncCryptoRSAKeyPair *key_pair)
 {
-  JsonNode *node = NULL;
-  JsonObject *json = NULL;
-  GError *error = NULL;
-  guint8 *aes_key = NULL;
-  guint8 *hmac_key = NULL;
-  guint8 *ciphertext = NULL;
-  guint8 *iv = NULL;
-  char *cleartext = NULL;
-  const char *ciphertext_b64;
-  const char *iv_b64;
-  const char *hmac;
-  gsize ciphertext_len;
-  gsize iv_len;
+  mpz_t signature;
+  const char *header = "{\"alg\": \"RS256\"}";
+  char *body;
+  char *body_b64;
+  char *header_b64;
+  char *to_sign;
+  char *sig_b64;
+  char *assertion;
+  char *digest_hex;
+  guint8 *digest;
+  guint8 *sig;
+  guint64 expires_at;
+  gsize expected_size;
+  gsize count;
+  int success;
 
-  g_return_val_if_fail (payload, NULL);
-  g_return_val_if_fail (bundle, NULL);
+  g_return_val_if_fail (certificate, NULL);
+  g_return_val_if_fail (audience, NULL);
+  g_return_val_if_fail (key_pair, NULL);
 
-  /* Extract ciphertext, iv and hmac from payload. */
-  node = json_from_string (payload, &error);
-  if (error) {
-    g_warning ("Payload is not a valid JSON: %s", error->message);
-    goto out;
-  }
-  json = json_node_get_object (node);
-  if (!json) {
-    g_warning ("JSON node does not hold a JSON object");
-    goto out;
-  }
-  ciphertext_b64 = json_object_get_string_member (json, "ciphertext");
-  iv_b64 = json_object_get_string_member (json, "IV");
-  hmac = json_object_get_string_member (json, "hmac");
-  if (!ciphertext_b64 || !iv_b64 || !hmac) {
-    g_warning ("JSON object has missing or invalid members");
-    goto out;
-  }
+  /* Encode the header and body to base64 url safe and join them. */
+  expires_at = g_get_real_time () / 1000 + seconds * 1000;
+  body = g_strdup_printf ("{\"exp\": %lu, \"aud\": \"%s\"}", expires_at, audience);
+  body_b64 = ephy_sync_utils_base64_urlsafe_encode ((guint8 *)body, strlen (body), TRUE);
+  header_b64 = ephy_sync_utils_base64_urlsafe_encode ((guint8 *)header, strlen (header), TRUE);
+  to_sign = g_strdup_printf ("%s.%s", header_b64, body_b64);
 
-  /* Get the encryption key and the HMAC key. */
-  aes_key = ephy_sync_utils_decode_hex (bundle->aes_key_hex);
-  hmac_key = ephy_sync_utils_decode_hex (bundle->hmac_key_hex);
+  /* Compute the SHA256 hash of the message to be signed. */
+  digest_hex = g_compute_checksum_for_string (G_CHECKSUM_SHA256, to_sign, -1);
+  digest = ephy_sync_utils_decode_hex (digest_hex);
 
-  /* Under no circumstances should a client try to decrypt a record
-   * if the HMAC verification fails. */
-  if (!ephy_sync_crypto_hmac_is_valid (ciphertext_b64, hmac_key, hmac)) {
-    g_warning ("Incorrect HMAC value");
-    goto out;
-  }
+  /* Use the provided key pair to RSA sign the message. */
+  mpz_init (signature);
+  success = rsa_sha256_sign_digest_tr (&key_pair->public, &key_pair->private,
+                                       NULL, ephy_sync_utils_generate_random_bytes,
+                                       digest, signature);
+  /* Given correct parameters, this never fails. */
+  g_assert (success);
 
-  /* Finally, decrypt the record. */
-  ciphertext = g_base64_decode (ciphertext_b64, &ciphertext_len);
-  iv = g_base64_decode (iv_b64, &iv_len);
-  cleartext = ephy_sync_crypto_aes_256_decrypt (ciphertext, ciphertext_len,
-                                                aes_key, iv);
+  expected_size = (mpz_sizeinbase (signature, 2) + 7) / 8;
+  sig = g_malloc (expected_size);
+  mpz_export (sig, &count, 1, sizeof (guint8), 0, 0, signature);
+  /* Given correct parameters, this never fails. */
+  g_assert (count == expected_size);
 
-out:
-  g_free (ciphertext);
-  g_free (iv);
-  g_free (aes_key);
-  g_free (hmac_key);
-  if (node)
-    json_node_unref (node);
-  if (error)
-    g_error_free (error);
+  /* Join certificate, header, body and signed message to create the assertion. */
+  sig_b64 = ephy_sync_utils_base64_urlsafe_encode (sig, count, TRUE);
+  assertion = g_strdup_printf ("%s~%s.%s.%s", certificate, header_b64, body_b64, sig_b64);
 
-  return cleartext;
+  g_free (body);
+  g_free (body_b64);
+  g_free (header_b64);
+  g_free (to_sign);
+  g_free (sig_b64);
+  g_free (sig);
+  g_free (digest_hex);
+  g_free (digest);
+  mpz_clear (signature);
+
+  return assertion;
+}
+
+static guint8 *
+ephy_sync_crypto_pad (const char *text,
+                      gsize       block_len,
+                      gsize      *out_len)
+{
+  guint8 *out;
+  gsize text_len = strlen (text);
+
+  g_assert (text);
+  g_assert (out_len);
+
+  if (text_len % block_len == 0)
+    *out_len = text_len;
+  else
+    *out_len = text_len + block_len - text_len % block_len;
+
+  out = g_malloc (*out_len);
+
+  if (text_len % block_len != 0)
+    memset (out, block_len - text_len % block_len, *out_len);
+
+  memcpy (out, text, text_len);
+
+  return out;
+}
+
+static guint8 *
+ephy_sync_crypto_aes_256_encrypt (const char   *text,
+                                  const guint8 *key,
+                                  const guint8 *iv,
+                                  gsize        *out_len)
+{
+  guint8 *padded;
+  guint8 *encrypted;
+  gsize padded_len;
+  struct CBC_CTX(struct aes256_ctx, AES_BLOCK_SIZE) ctx;
+
+  g_assert (text);
+  g_assert (key);
+  g_assert (iv);
+  g_assert (out_len);
+
+  padded = ephy_sync_crypto_pad (text, AES_BLOCK_SIZE, &padded_len);
+  encrypted = g_malloc (padded_len);
+
+  aes256_set_encrypt_key(&ctx.ctx, key);
+  CBC_SET_IV(&ctx, iv);
+  CBC_ENCRYPT(&ctx, aes256_encrypt, padded_len, encrypted, padded);
+
+  *out_len = padded_len;
+  g_free (padded);
+
+  return encrypted;
 }
 
 char *
@@ -1059,214 +1109,141 @@ ephy_sync_crypto_encrypt_record (const char          *cleartext,
   return payload;
 }
 
-SyncCryptoHawkHeader *
-ephy_sync_crypto_compute_hawk_header (const char            *url,
-                                      const char            *method,
-                                      const char            *id,
-                                      const guint8          *key,
-                                      gsize                  key_len,
-                                      SyncCryptoHawkOptions *options)
+static gboolean
+ephy_sync_crypto_hmac_is_valid (const char   *text,
+                                const guint8 *key,
+                                const char   *expected)
 {
-  SyncCryptoHawkHeader *hawk_header;
-  SyncCryptoHawkArtifacts *artifacts;
-  SoupURI *uri;
-  char *resource;
-  char *hash;
-  char *header;
-  char *mac;
-  char *nonce;
-  char *payload;
-  char *timestamp;
-  guint8 *bytes;
-  gint64 ts;
-
-  g_return_val_if_fail (url, NULL);
-  g_return_val_if_fail (method, NULL);
-  g_return_val_if_fail (id, NULL);
-  g_return_val_if_fail (key, NULL);
-
-  ts = g_get_real_time () / 1000000;
-  hash = options ? g_strdup (options->hash) : NULL;
-  payload = options ? options->payload : NULL;
-  timestamp = options ? options->timestamp : NULL;
-  uri = soup_uri_new (url);
-  resource = !soup_uri_get_query (uri) ? g_strdup (soup_uri_get_path (uri))
-                                       : g_strconcat (soup_uri_get_path (uri),
-                                                      "?",
-                                                      soup_uri_get_query (uri),
-                                                      NULL);
-
-  if (options && options->nonce) {
-    nonce = g_strdup (options->nonce);
-  } else {
-    bytes = g_malloc (NONCE_LEN / 2);
-    ephy_sync_utils_generate_random_bytes (NULL, NONCE_LEN / 2, bytes);
-    nonce = ephy_sync_utils_encode_hex (bytes, NONCE_LEN / 2);
-    g_free (bytes);
-  }
-
-  if (timestamp) {
-    char *local_time_offset;
-    gint64 offset;
-
-    local_time_offset = options ? options->local_time_offset : NULL;
-    offset = local_time_offset ? g_ascii_strtoll (local_time_offset, NULL, 10) : 0;
-    ts = g_ascii_strtoll (timestamp, NULL, 10) + offset;
-  }
-
-  if (!hash && payload) {
-    const char *content_type = options ? options->content_type : "text/plain";
-
-    /* Calculate hash for the given payload. */
-    hash = ephy_sync_crypto_calculate_payload_hash (payload, content_type);
-  }
-
-  /* Create artifacts from options. */
-  artifacts = ephy_sync_crypto_hawk_artifacts_new (options ? options->app : NULL,
-                                                   options ? options->dlg : NULL,
-                                                   options ? options->ext : NULL,
-                                                   hash,
-                                                   soup_uri_get_host (uri),
-                                                   method,
-                                                   nonce,
-                                                   soup_uri_get_port (uri),
-                                                   resource,
-                                                   ts);
-
-  header = g_strconcat ("Hawk id=\"", id, "\"",
-                        ", ts=\"", artifacts->ts, "\"",
-                        ", nonce=\"", artifacts->nonce, "\"",
-                        NULL);
-
-  /* Append pre-calculated payload hash if any. */
-  if (artifacts->hash && strlen (artifacts->hash) > 0)
-    header = ephy_sync_crypto_append_to_header (header, "hash", artifacts->hash);
-
-  /* Append the application specific data if any. */
-  if (artifacts->ext && strlen (artifacts->ext) > 0) {
-    char *h_ext;
-    char *tmp_ext;
+  char *hmac;
+  gboolean retval;
 
-    tmp_ext = ephy_sync_crypto_find_and_replace (artifacts->ext, "\\", "\\\\");
-    h_ext = ephy_sync_crypto_find_and_replace (tmp_ext, "\n", "\\n");
-    header = ephy_sync_crypto_append_to_header (header, "ext", h_ext);
+  g_assert (text);
+  g_assert (key);
+  g_assert (expected);
 
-    g_free (h_ext);
-    g_free (tmp_ext);
-  }
+  /* SHA256 expects a 32 bytes key. */
+  hmac = g_compute_hmac_for_string (G_CHECKSUM_SHA256, key, 32, text, -1);
+  retval = g_strcmp0 (hmac, expected) == 0;
+  g_free (hmac);
 
-  /* Calculate and append a message authentication code (MAC). */
-  mac = ephy_sync_crypto_calculate_mac ("header", key, key_len, artifacts);
-  header = ephy_sync_crypto_append_to_header (header, "mac", mac);
+  return retval;
+}
 
-  /* Append the Oz application id if any. */
-  if (artifacts->app) {
-    header = ephy_sync_crypto_append_to_header (header, "app", artifacts->app);
+static char *
+ephy_sync_crypto_unpad (const guint8 *data,
+                        gsize         data_len,
+                        gsize         block_len)
+{
+  char *out;
+  gsize out_len;
+  gsize padding = data[data_len - 1];
 
-    /* Append the Oz delegated-by application id if any. */
-    if (artifacts->dlg)
-      header = ephy_sync_crypto_append_to_header (header, "dlg", artifacts->dlg);
-  }
+  g_assert (data);
 
-  hawk_header = ephy_sync_crypto_hawk_header_new (header, artifacts);
+  if (padding >= 1 && padding <= block_len)
+    out_len = data_len - padding;
+  else
+    out_len = data_len;
 
-  soup_uri_free (uri);
-  g_free (hash);
-  g_free (mac);
-  g_free (nonce);
-  g_free (resource);
-  g_free (header);
+  out = g_malloc0 (out_len + 1);
+  memcpy (out, data, out_len);
 
-  return hawk_header;
+  return out;
 }
 
-SyncCryptoRSAKeyPair *
-ephy_sync_crypto_generate_rsa_key_pair (void)
+static char *
+ephy_sync_crypto_aes_256_decrypt (const guint8 *data,
+                                  gsize         data_len,
+                                  const guint8 *key,
+                                  const guint8 *iv)
 {
-  struct rsa_public_key public;
-  struct rsa_private_key private;
-  int success;
+  guint8 *decrypted;
+  char *unpadded;
+  struct CBC_CTX(struct aes256_ctx, AES_BLOCK_SIZE) ctx;
 
-  rsa_public_key_init (&public);
-  rsa_private_key_init (&private);
+  g_assert (data);
+  g_assert (key);
+  g_assert (iv);
 
-  /* The public exponent, usually one of the small Fermat primes 3, 5, 17, 257, 65537. */
-  mpz_set_ui (public.e, 65537);
+  decrypted = g_malloc (data_len);
 
-  /* Key sizes below 2048 are considered breakable and should not be used. */
-  success = rsa_generate_keypair (&public, &private,
-                                  NULL, ephy_sync_utils_generate_random_bytes,
-                                  NULL, NULL, 2048, 0);
-  /* Given correct parameters, this never fails. */
-  g_assert (success);
+  aes256_set_decrypt_key (&ctx.ctx, key);
+  CBC_SET_IV (&ctx, iv);
+  CBC_DECRYPT (&ctx, aes256_decrypt, data_len, decrypted, data);
 
-  return ephy_sync_crypto_rsa_key_pair_new (public, private);
+  unpadded = ephy_sync_crypto_unpad (decrypted, data_len, AES_BLOCK_SIZE);
+  g_free (decrypted);
+
+  return unpadded;
 }
 
 char *
-ephy_sync_crypto_create_assertion (const char           *certificate,
-                                   const char           *audience,
-                                   guint64               seconds,
-                                   SyncCryptoRSAKeyPair *rsa_key_pair)
+ephy_sync_crypto_decrypt_record (const char          *payload,
+                                 SyncCryptoKeyBundle *bundle)
 {
-  mpz_t signature;
-  const char *header = "{\"alg\": \"RS256\"}";
-  char *body;
-  char *body_b64;
-  char *header_b64;
-  char *to_sign;
-  char *sig_b64;
-  char *assertion;
-  char *digest_hex;
-  guint8 *digest;
-  guint8 *sig;
-  guint64 expires_at;
-  gsize expected_size;
-  gsize count;
-  int success;
-
-  g_return_val_if_fail (certificate, NULL);
-  g_return_val_if_fail (audience, NULL);
-  g_return_val_if_fail (rsa_key_pair, NULL);
+  JsonNode *node = NULL;
+  JsonObject *json = NULL;
+  GError *error = NULL;
+  guint8 *aes_key = NULL;
+  guint8 *hmac_key = NULL;
+  guint8 *ciphertext = NULL;
+  guint8 *iv = NULL;
+  char *cleartext = NULL;
+  const char *ciphertext_b64;
+  const char *iv_b64;
+  const char *hmac;
+  gsize ciphertext_len;
+  gsize iv_len;
 
-  /* Encode the header and body to base64 url safe and join them. */
-  expires_at = g_get_real_time () / 1000 + seconds * 1000;
-  body = g_strdup_printf ("{\"exp\": %lu, \"aud\": \"%s\"}", expires_at, audience);
-  body_b64 = ephy_sync_utils_base64_urlsafe_encode ((guint8 *)body, strlen (body), TRUE);
-  header_b64 = ephy_sync_utils_base64_urlsafe_encode ((guint8 *)header, strlen (header), TRUE);
-  to_sign = g_strdup_printf ("%s.%s", header_b64, body_b64);
+  g_return_val_if_fail (payload, NULL);
+  g_return_val_if_fail (bundle, NULL);
 
-  /* Compute the SHA256 hash of the message to be signed. */
-  digest_hex = g_compute_checksum_for_string (G_CHECKSUM_SHA256, to_sign, -1);
-  digest = ephy_sync_utils_decode_hex (digest_hex);
+  /* Extract ciphertext, iv and hmac from payload. */
+  node = json_from_string (payload, &error);
+  if (error) {
+    g_warning ("Payload is not a valid JSON: %s", error->message);
+    goto out;
+  }
+  json = json_node_get_object (node);
+  if (!json) {
+    g_warning ("JSON node does not hold a JSON object");
+    goto out;
+  }
+  ciphertext_b64 = json_object_get_string_member (json, "ciphertext");
+  iv_b64 = json_object_get_string_member (json, "IV");
+  hmac = json_object_get_string_member (json, "hmac");
+  if (!ciphertext_b64 || !iv_b64 || !hmac) {
+    g_warning ("JSON object has missing or invalid members");
+    goto out;
+  }
 
-  /* Use the provided key pair to RSA sign the message. */
-  mpz_init (signature);
-  success = rsa_sha256_sign_digest_tr (&rsa_key_pair->public, &rsa_key_pair->private,
-                                       NULL, ephy_sync_utils_generate_random_bytes,
-                                       digest, signature);
-  /* Given correct parameters, this never fails. */
-  g_assert (success);
+  /* Get the encryption key and the HMAC key. */
+  aes_key = ephy_sync_utils_decode_hex (bundle->aes_key_hex);
+  hmac_key = ephy_sync_utils_decode_hex (bundle->hmac_key_hex);
 
-  expected_size = (mpz_sizeinbase (signature, 2) + 7) / 8;
-  sig = g_malloc (expected_size);
-  mpz_export (sig, &count, 1, sizeof (guint8), 0, 0, signature);
-  /* Given correct parameters, this never fails. */
-  g_assert (count == expected_size);
+  /* Under no circumstances should a client try to decrypt a record
+   * if the HMAC verification fails.
+   */
+  if (!ephy_sync_crypto_hmac_is_valid (ciphertext_b64, hmac_key, hmac)) {
+    g_warning ("Incorrect HMAC value");
+    goto out;
+  }
 
-  /* Join certificate, header, body and signed message to create the assertion. */
-  sig_b64 = ephy_sync_utils_base64_urlsafe_encode (sig, count, TRUE);
-  assertion = g_strdup_printf ("%s~%s.%s.%s", certificate, header_b64, body_b64, sig_b64);
+  /* Finally, decrypt the record. */
+  ciphertext = g_base64_decode (ciphertext_b64, &ciphertext_len);
+  iv = g_base64_decode (iv_b64, &iv_len);
+  cleartext = ephy_sync_crypto_aes_256_decrypt (ciphertext, ciphertext_len,
+                                                aes_key, iv);
 
-  g_free (body);
-  g_free (body_b64);
-  g_free (header_b64);
-  g_free (to_sign);
-  g_free (sig_b64);
-  g_free (sig);
-  g_free (digest_hex);
-  g_free (digest);
-  mpz_clear (signature);
+out:
+  g_free (ciphertext);
+  g_free (iv);
+  g_free (aes_key);
+  g_free (hmac_key);
+  if (node)
+    json_node_unref (node);
+  if (error)
+    g_error_free (error);
 
-  return assertion;
+  return cleartext;
 }
diff --git a/lib/sync/ephy-sync-crypto.h b/lib/sync/ephy-sync-crypto.h
index 3b275ce..be52d6f 100644
--- a/lib/sync/ephy-sync-crypto.h
+++ b/lib/sync/ephy-sync-crypto.h
@@ -66,55 +66,57 @@ typedef struct {
   char *hmac_key_hex;
 } SyncCryptoKeyBundle;
 
-SyncCryptoHawkOptions  *ephy_sync_crypto_hawk_options_new         (const char *app,
-                                                                   const char *dlg,
-                                                                   const char *ext,
-                                                                   const char *content_type,
-                                                                   const char *hash,
-                                                                   const char *local_time_offset,
-                                                                   const char *nonce,
-                                                                   const char *payload,
-                                                                   const char *timestamp);
-void                    ephy_sync_crypto_hawk_options_free        (SyncCryptoHawkOptions *options);
-void                    ephy_sync_crypto_hawk_header_free         (SyncCryptoHawkHeader *header);
-void                    ephy_sync_crypto_rsa_key_pair_free        (SyncCryptoRSAKeyPair *rsa_key_pair);
-SyncCryptoKeyBundle    *ephy_sync_crypto_key_bundle_from_array    (JsonArray *array);
-void                    ephy_sync_crypto_key_bundle_free          (SyncCryptoKeyBundle *bundle);
-void                    ephy_sync_crypto_process_key_fetch_token  (const char  *key_fetch_token,
-                                                                   guint8     **token_id,
-                                                                   guint8     **req_hmac_key,
-                                                                   guint8     **resp_hmac_key,
-                                                                   guint8     **resp_xor_key,
-                                                                   gsize        token_len);
-void                    ephy_sync_crypto_process_session_token    (const char  *session_token,
-                                                                   guint8     **token_id,
-                                                                   guint8     **req_hmac_key,
-                                                                   guint8     **requestKey,
-                                                                   gsize        token_len);
-gboolean                ephy_sync_crypto_compute_sync_keys        (const char    *bundle_hex,
-                                                                   const guint8  *resp_hmac_key,
-                                                                   const guint8  *resp_xor_key,
-                                                                   const guint8  *unwrap_b_key,
-                                                                   guint8       **key_a,
-                                                                   guint8       **key_b,
-                                                                   gsize          key_len);
-SyncCryptoKeyBundle    *ephy_sync_crypto_derive_key_bundle        (const guint8 *key,
-                                                                   gsize         key_len);
-char                   *ephy_sync_crypto_generate_crypto_keys     (gsize key_len);
-char                   *ephy_sync_crypto_decrypt_record           (const char          *payload,
-                                                                   SyncCryptoKeyBundle *bundle);
-char                   *ephy_sync_crypto_encrypt_record           (const char          *cleartext,
-                                                                   SyncCryptoKeyBundle *bundle);
-SyncCryptoHawkHeader   *ephy_sync_crypto_compute_hawk_header      (const char            *url,
-                                                                   const char            *method,
-                                                                   const char            *id,
-                                                                   const guint8          *key,
-                                                                   gsize                  key_len,
-                                                                   SyncCryptoHawkOptions *options);
-SyncCryptoRSAKeyPair   *ephy_sync_crypto_generate_rsa_key_pair    (void);
-char                   *ephy_sync_crypto_create_assertion         (const char           *certificate,
-                                                                   const char           *audience,
-                                                                   guint64               duration,
-                                                                   SyncCryptoRSAKeyPair *rsa_key_pair);
+SyncCryptoHawkOptions *ephy_sync_crypto_hawk_options_new        (const char *app,
+                                                                 const char *dlg,
+                                                                 const char *ext,
+                                                                 const char *content_type,
+                                                                 const char *hash,
+                                                                 const char *local_time_offset,
+                                                                 const char *nonce,
+                                                                 const char *payload,
+                                                                 const char *timestamp);
+void                   ephy_sync_crypto_hawk_options_free       (SyncCryptoHawkOptions *options);
+
+SyncCryptoHawkHeader  *ephy_sync_crypto_hawk_header_new         (const char            *url,
+                                                                 const char            *method,
+                                                                 const char            *id,
+                                                                 const guint8          *key,
+                                                                 gsize                  key_len,
+                                                                 SyncCryptoHawkOptions *options);
+void                   ephy_sync_crypto_hawk_header_free        (SyncCryptoHawkHeader *header);
+
+SyncCryptoRSAKeyPair  *ephy_sync_crypto_rsa_key_pair_new        (void);
+void                   ephy_sync_crypto_rsa_key_pair_free       (SyncCryptoRSAKeyPair *key_pair);
+
+SyncCryptoKeyBundle   *ephy_sync_crypto_key_bundle_new          (JsonArray *array);
+void                   ephy_sync_crypto_key_bundle_free         (SyncCryptoKeyBundle *bundle);
+
+void                   ephy_sync_crypto_derive_session_token    (const char  *session_token,
+                                                                 guint8     **token_id,
+                                                                 guint8     **req_hmac_key,
+                                                                 guint8     **requestKey);
+void                   ephy_sync_crypto_derive_key_fetch_token  (const char  *key_fetch_token,
+                                                                 guint8     **token_id,
+                                                                 guint8     **req_hmac_key,
+                                                                 guint8     **resp_hmac_key,
+                                                                 guint8     **resp_xor_key);
+gboolean               ephy_sync_crypto_derive_master_keys      (const char    *bundle_hex,
+                                                                 const guint8  *resp_hmac_key,
+                                                                 const guint8  *resp_xor_key,
+                                                                 const guint8  *unwrap_kb,
+                                                                 guint8       **ka,
+                                                                 guint8       **kb);
+SyncCryptoKeyBundle   *ephy_sync_crypto_derive_master_bundle    (const guint8 *kb);
+
+char                  *ephy_sync_crypto_generate_crypto_keys    (void);
+char                  *ephy_sync_crypto_create_assertion        (const char           *certificate,
+                                                                 const char           *audience,
+                                                                 guint64               duration,
+                                                                 SyncCryptoRSAKeyPair *key_pair);
+
+char                  *ephy_sync_crypto_encrypt_record          (const char          *cleartext,
+                                                                 SyncCryptoKeyBundle *bundle);
+char                  *ephy_sync_crypto_decrypt_record          (const char          *payload,
+                                                                 SyncCryptoKeyBundle *bundle);
 
 G_END_DECLS
diff --git a/lib/sync/ephy-sync-service.c b/lib/sync/ephy-sync-service.c
index e55b4b3..ee1e0de 100644
--- a/lib/sync/ephy-sync-service.c
+++ b/lib/sync/ephy-sync-service.c
@@ -52,7 +52,7 @@ struct _EphySyncService {
   GQueue      *storage_queue;
 
   char                 *certificate;
-  SyncCryptoRSAKeyPair *rsa_key_pair;
+  SyncCryptoRSAKeyPair *key_pair;
 
   gboolean sync_periodically;
   gboolean is_signing_in;
@@ -107,7 +107,7 @@ typedef struct {
   char            *email;
   char            *uid;
   char            *session_token;
-  char            *unwrap_b_key;
+  char            *unwrap_kb;
   char            *token_id_hex;
   guint8          *req_hmac_key;
   guint8          *resp_hmac_key;
@@ -168,7 +168,7 @@ sign_in_async_data_new (EphySyncService *service,
                         const char      *email,
                         const char      *uid,
                         const char      *session_token,
-                        const char      *unwrap_b_key,
+                        const char      *unwrap_kb,
                         const char      *token_id_hex,
                         const guint8    *req_hmac_key,
                         const guint8    *resp_hmac_key,
@@ -181,7 +181,7 @@ sign_in_async_data_new (EphySyncService *service,
   data->email = g_strdup (email);
   data->uid = g_strdup (uid);
   data->session_token = g_strdup (session_token);
-  data->unwrap_b_key = g_strdup (unwrap_b_key);
+  data->unwrap_kb = g_strdup (unwrap_kb);
   data->token_id_hex = g_strdup (token_id_hex);
   data->req_hmac_key = g_malloc (32);
   memcpy (data->req_hmac_key, req_hmac_key, 32);
@@ -202,7 +202,7 @@ sign_in_async_data_free (SignInAsyncData *data)
   g_free (data->email);
   g_free (data->uid);
   g_free (data->session_token);
-  g_free (data->unwrap_b_key);
+  g_free (data->unwrap_kb);
   g_free (data->token_id_hex);
   g_free (data->req_hmac_key);
   g_free (data->resp_hmac_key);
@@ -346,7 +346,7 @@ ephy_sync_service_get_key_bundle (EphySyncService *self,
   array = json_object_has_member (collections, collection) ?
           json_object_get_array_member (collections, collection) :
           json_object_get_array_member (json, "default");
-  bundle = ephy_sync_crypto_key_bundle_from_array (array);
+  bundle = ephy_sync_crypto_key_bundle_new (array);
 
   json_node_unref (node);
 
@@ -381,17 +381,17 @@ ephy_sync_service_storage_credentials_is_expired (EphySyncService *self)
 }
 
 static void
-ephy_sync_service_fxa_hawk_post_async (EphySyncService     *self,
-                                       const char          *endpoint,
-                                       const char          *id,
-                                       guint8              *key,
-                                       gsize                key_len,
-                                       char                *request_body,
-                                       SoupSessionCallback  callback,
-                                       gpointer             user_data)
-{
-  SyncCryptoHawkOptions *hawk_options;
-  SyncCryptoHawkHeader *hawk_header;
+ephy_sync_service_fxa_hawk_post (EphySyncService     *self,
+                                 const char          *endpoint,
+                                 const char          *id,
+                                 guint8              *key,
+                                 gsize                key_len,
+                                 const char          *request_body,
+                                 SoupSessionCallback  callback,
+                                 gpointer             user_data)
+{
+  SyncCryptoHawkOptions *options;
+  SyncCryptoHawkHeader *header;
   SoupMessage *msg;
   char *url;
   const char *content_type = "application/json; charset=utf-8";
@@ -407,35 +407,29 @@ ephy_sync_service_fxa_hawk_post_async (EphySyncService     *self,
   soup_message_set_request (msg, content_type, SOUP_MEMORY_COPY,
                             request_body, strlen (request_body));
 
-  hawk_options = ephy_sync_crypto_hawk_options_new (NULL, NULL, NULL,
-                                                    content_type,
-                                                    NULL, NULL, NULL,
-                                                    request_body,
-                                                    NULL);
-  hawk_header = ephy_sync_crypto_compute_hawk_header (url, "POST", id,
-                                                      key, key_len,
-                                                      hawk_options);
-  soup_message_headers_append (msg->request_headers,
-                               "authorization", hawk_header->header);
-  soup_message_headers_append (msg->request_headers,
-                               "content-type", content_type);
+  options = ephy_sync_crypto_hawk_options_new (NULL, NULL, NULL, content_type,
+                                               NULL, NULL, NULL, request_body,
+                                               NULL);
+  header = ephy_sync_crypto_hawk_header_new (url, "POST", id, key, key_len, options);
+  soup_message_headers_append (msg->request_headers, "authorization", header->header);
+  soup_message_headers_append (msg->request_headers, "content-type", content_type);
   soup_session_queue_message (self->session, msg, callback, user_data);
 
   g_free (url);
-  ephy_sync_crypto_hawk_options_free (hawk_options);
-  ephy_sync_crypto_hawk_header_free (hawk_header);
+  ephy_sync_crypto_hawk_options_free (options);
+  ephy_sync_crypto_hawk_header_free (header);
 }
 
 static void
-ephy_sync_service_fxa_hawk_get_async (EphySyncService     *self,
-                                      const char          *endpoint,
-                                      const char          *id,
-                                      guint8              *key,
-                                      gsize                key_len,
-                                      SoupSessionCallback  callback,
-                                      gpointer             user_data)
-{
-  SyncCryptoHawkHeader *hawk_header;
+ephy_sync_service_fxa_hawk_get (EphySyncService     *self,
+                                const char          *endpoint,
+                                const char          *id,
+                                guint8              *key,
+                                gsize                key_len,
+                                SoupSessionCallback  callback,
+                                gpointer             user_data)
+{
+  SyncCryptoHawkHeader *header;
   SoupMessage *msg;
   char *url;
 
@@ -446,22 +440,20 @@ ephy_sync_service_fxa_hawk_get_async (EphySyncService     *self,
 
   url = g_strdup_printf ("%s/%s", FIREFOX_ACCOUNTS_SERVER_URL, endpoint);
   msg = soup_message_new (SOUP_METHOD_GET, url);
-  hawk_header = ephy_sync_crypto_compute_hawk_header (url, "GET", id,
-                                                      key, key_len,
-                                                      NULL);
-  soup_message_headers_append (msg->request_headers, "authorization", hawk_header->header);
+  header = ephy_sync_crypto_hawk_header_new (url, "GET", id, key, key_len, NULL);
+  soup_message_headers_append (msg->request_headers, "authorization", header->header);
   soup_session_queue_message (self->session, msg, callback, user_data);
 
   g_free (url);
-  ephy_sync_crypto_hawk_header_free (hawk_header);
+  ephy_sync_crypto_hawk_header_free (header);
 }
 
 static void
 ephy_sync_service_send_storage_request (EphySyncService         *self,
                                         StorageRequestAsyncData *data)
 {
-  SyncCryptoHawkOptions *hawk_options = NULL;
-  SyncCryptoHawkHeader *hawk_header;
+  SyncCryptoHawkOptions *options = NULL;
+  SyncCryptoHawkHeader *header;
   SoupMessage *msg;
   char *url;
   char *if_modified_since = NULL;
@@ -475,53 +467,46 @@ ephy_sync_service_send_storage_request (EphySyncService         *self,
   msg = soup_message_new (data->method, url);
 
   if (data->request_body) {
-    hawk_options = ephy_sync_crypto_hawk_options_new (NULL, NULL, NULL,
-                                                      content_type,
-                                                      NULL, NULL, NULL,
-                                                      data->request_body,
-                                                      NULL);
+    options = ephy_sync_crypto_hawk_options_new (NULL, NULL, NULL, content_type,
+                                                 NULL, NULL, NULL, data->request_body,
+                                                 NULL);
     soup_message_set_request (msg, content_type, SOUP_MEMORY_COPY,
                               data->request_body, strlen (data->request_body));
   }
 
   if (!g_strcmp0 (data->method, SOUP_METHOD_PUT))
-    soup_message_headers_append (msg->request_headers,
-                                 "content-type", content_type);
+    soup_message_headers_append (msg->request_headers, "content-type", content_type);
 
   if (data->modified_since >= 0) {
     if_modified_since = g_strdup_printf ("%.2lf", data->modified_since);
-    soup_message_headers_append (msg->request_headers,
-                                 "X-If-Modified-Since", if_modified_since);
+    soup_message_headers_append (msg->request_headers, "X-If-Modified-Since", if_modified_since);
   }
 
   if (data->unmodified_since >= 0) {
     if_unmodified_since = g_strdup_printf ("%.2lf", data->unmodified_since);
-    soup_message_headers_append (msg->request_headers,
-                                 "X-If-Unmodified-Since", if_unmodified_since);
+    soup_message_headers_append (msg->request_headers, "X-If-Unmodified-Since", if_unmodified_since);
   }
 
-  hawk_header = ephy_sync_crypto_compute_hawk_header (url, data->method,
-                                                      self->storage_credentials_id,
-                                                      (guint8 *)self->storage_credentials_key,
-                                                      strlen (self->storage_credentials_key),
-                                                      hawk_options);
-  soup_message_headers_append (msg->request_headers,
-                               "authorization", hawk_header->header);
+  header = ephy_sync_crypto_hawk_header_new (url, data->method,
+                                             self->storage_credentials_id,
+                                             (guint8 *)self->storage_credentials_key,
+                                             strlen (self->storage_credentials_key),
+                                             options);
+  soup_message_headers_append (msg->request_headers, "authorization", header->header);
   soup_session_queue_message (self->session, msg, data->callback, data->user_data);
 
-  if (hawk_options)
-    ephy_sync_crypto_hawk_options_free (hawk_options);
-
   g_free (url);
   g_free (if_modified_since);
   g_free (if_unmodified_since);
-  ephy_sync_crypto_hawk_header_free (hawk_header);
+  ephy_sync_crypto_hawk_header_free (header);
+  if (options)
+    ephy_sync_crypto_hawk_options_free (options);
   storage_request_async_data_free (data);
 }
 
 static gboolean
-ephy_sync_service_certificate_is_valid (EphySyncService *self,
-                                        const char      *certificate)
+ephy_sync_service_verify_certificate (EphySyncService *self,
+                                      const char      *certificate)
 {
   JsonParser *parser;
   JsonObject *json;
@@ -668,12 +653,12 @@ static void
 ephy_sync_service_destroy_session (EphySyncService *self,
                                    const char      *session_token)
 {
-  SyncCryptoHawkOptions *hawk_options;
-  SyncCryptoHawkHeader *hawk_header;
+  SyncCryptoHawkOptions *options;
+  SyncCryptoHawkHeader *header;
   SoupMessage *msg;
   guint8 *token_id;
   guint8 *req_hmac_key;
-  guint8 *request_key;
+  guint8 *tmp;
   char *token_id_hex;
   char *url;
   const char *content_type = "application/json; charset=utf-8";
@@ -685,34 +670,29 @@ ephy_sync_service_destroy_session (EphySyncService *self,
   g_assert (session_token);
 
   url = g_strdup_printf ("%s/session/destroy", FIREFOX_ACCOUNTS_SERVER_URL);
-  ephy_sync_crypto_process_session_token (session_token, &token_id,
-                                          &req_hmac_key, &request_key, 32);
+  ephy_sync_crypto_derive_session_token (session_token, &token_id,
+                                         &req_hmac_key, &tmp);
   token_id_hex = ephy_sync_utils_encode_hex (token_id, 32);
 
   msg = soup_message_new (SOUP_METHOD_POST, url);
   soup_message_set_request (msg, content_type, SOUP_MEMORY_STATIC,
                             request_body, strlen (request_body));
-  hawk_options = ephy_sync_crypto_hawk_options_new (NULL, NULL, NULL,
-                                                    content_type,
-                                                    NULL, NULL, NULL,
-                                                    request_body,
-                                                    NULL);
-  hawk_header = ephy_sync_crypto_compute_hawk_header (url, "POST", token_id_hex,
-                                                      req_hmac_key, 32,
-                                                      hawk_options);
-  soup_message_headers_append (msg->request_headers,
-                               "authorization", hawk_header->header);
-  soup_message_headers_append (msg->request_headers,
-                               "content-type", content_type);
+  options = ephy_sync_crypto_hawk_options_new (NULL, NULL, NULL, content_type,
+                                               NULL, NULL, NULL, request_body,
+                                               NULL);
+  header = ephy_sync_crypto_hawk_header_new (url, "POST", token_id_hex,
+                                             req_hmac_key, 32, options);
+  soup_message_headers_append (msg->request_headers, "authorization", header->header);
+  soup_message_headers_append (msg->request_headers, "content-type", content_type);
   soup_session_queue_message (self->session, msg, destroy_session_cb, self);
 
   g_free (token_id_hex);
   g_free (token_id);
   g_free (req_hmac_key);
-  g_free (request_key);
+  g_free (tmp);
   g_free (url);
-  ephy_sync_crypto_hawk_options_free (hawk_options);
-  ephy_sync_crypto_hawk_header_free (hawk_header);
+  ephy_sync_crypto_hawk_options_free (options);
+  ephy_sync_crypto_hawk_header_free (header);
 }
 
 static void
@@ -736,9 +716,9 @@ ephy_sync_service_report_sign_in_error (EphySyncService *self,
 }
 
 static void
-obtain_storage_credentials_cb (SoupSession *session,
-                               SoupMessage *msg,
-                               gpointer     user_data)
+get_storage_credentials_cb (SoupSession *session,
+                            SoupMessage *msg,
+                            gpointer     user_data)
 {
   EphySyncService *self = EPHY_SYNC_SERVICE (user_data);
   JsonNode *node = NULL;
@@ -800,11 +780,11 @@ out:
 }
 
 static void
-ephy_sync_service_obtain_storage_credentials (EphySyncService *self)
+ephy_sync_service_trade_browserid_assertion (EphySyncService *self)
 {
   SoupMessage *msg;
-  guint8 *key_b;
-  char *hashed_key_b;
+  guint8 *kb;
+  char *hashed_kb;
   char *client_state;
   char *audience;
   char *assertion;
@@ -812,25 +792,26 @@ ephy_sync_service_obtain_storage_credentials (EphySyncService *self)
 
   g_assert (EPHY_IS_SYNC_SERVICE (self));
   g_assert (self->certificate);
-  g_assert (self->rsa_key_pair);
+  g_assert (self->key_pair);
 
   audience = ephy_sync_utils_get_audience (TOKEN_SERVER_URL);
   assertion = ephy_sync_crypto_create_assertion (self->certificate, audience,
-                                                 300, self->rsa_key_pair);
-  key_b = ephy_sync_utils_decode_hex (ephy_sync_service_get_secret (self, secrets[MASTER_KEY]));
-  hashed_key_b = g_compute_checksum_for_data (G_CHECKSUM_SHA256, key_b, 32);
-  client_state = g_strndup (hashed_key_b, 32);
+                                                 300, self->key_pair);
+  kb = ephy_sync_utils_decode_hex (ephy_sync_service_get_secret (self, secrets[MASTER_KEY]));
+  hashed_kb = g_compute_checksum_for_data (G_CHECKSUM_SHA256, kb, 32);
+  client_state = g_strndup (hashed_kb, 32);
   authorization = g_strdup_printf ("BrowserID %s", assertion);
 
   msg = soup_message_new (SOUP_METHOD_GET, TOKEN_SERVER_URL);
   /* We need to add the X-Client-State header so that the Token Server will
-   * recognize accounts that were previously used to sync Firefox data too. */
+   * recognize accounts that were previously used to sync Firefox data too.
+   */
   soup_message_headers_append (msg->request_headers, "X-Client-State", client_state);
   soup_message_headers_append (msg->request_headers, "authorization", authorization);
-  soup_session_queue_message (self->session, msg, obtain_storage_credentials_cb, self);
+  soup_session_queue_message (self->session, msg, get_storage_credentials_cb, self);
 
-  g_free (key_b);
-  g_free (hashed_key_b);
+  g_free (kb);
+  g_free (hashed_kb);
   g_free (client_state);
   g_free (audience);
   g_free (assertion);
@@ -838,9 +819,9 @@ ephy_sync_service_obtain_storage_credentials (EphySyncService *self)
 }
 
 static void
-obtain_signed_certificate_cb (SoupSession *session,
-                              SoupMessage *msg,
-                              gpointer     user_data)
+get_signed_certificate_cb (SoupSession *session,
+                           SoupMessage *msg,
+                           gpointer     user_data)
 {
   EphySyncService *self = EPHY_SYNC_SERVICE (user_data);
   JsonNode *node = NULL;
@@ -867,24 +848,27 @@ obtain_signed_certificate_cb (SoupSession *session,
       g_warning ("JSON object has missing or invalid 'cert' member");
       goto out_error;
     }
-    if (!ephy_sync_service_certificate_is_valid (self, certificate)) {
+
+    if (!ephy_sync_service_verify_certificate (self, certificate)) {
       g_warning ("Invalid certificate");
-      ephy_sync_crypto_rsa_key_pair_free (self->rsa_key_pair);
+      ephy_sync_crypto_rsa_key_pair_free (self->key_pair);
       goto out_error;
     }
+
     self->certificate = g_strdup (certificate);
-    ephy_sync_service_obtain_storage_credentials (self);
+    ephy_sync_service_trade_browserid_assertion (self);
     goto out_no_error;
   }
 
   /* Since a new Firefox Account password implies new tokens, this will fail
    * with an error code 110 (Invalid authentication token in request signature)
    * if the user has changed his password since the last time he signed in.
-   * When this happens, notify the user to sign in with the new password. */
+   * When this happens, notify the user to sign in with the new password.
+   */
   if (json_object_get_int_member (json, "errno") == 110) {
     message = _("The password of your Firefox account seems to have been changed.");
     suggestion = _("Please visit Preferences and sign in with the new password to continue syncing.");
-    ephy_sync_service_do_sign_out (self);
+    ephy_sync_service_sign_out (self);
   }
 
   g_warning ("Failed to sign certificate. Status code: %u, response: %s",
@@ -906,14 +890,14 @@ out_no_error:
 }
 
 static void
-ephy_sync_service_obtain_signed_certificate (EphySyncService *self)
+ephy_sync_service_get_storage_credentials (EphySyncService *self)
 {
   JsonNode *node;
   JsonObject *object_key;
   JsonObject *object_body;
   guint8 *token_id;
   guint8 *req_hmac_key;
-  guint8 *request_key;
+  guint8 *tmp;
   const char *session_token;
   char *token_id_hex;
   char *request_body;
@@ -922,19 +906,24 @@ ephy_sync_service_obtain_signed_certificate (EphySyncService *self)
 
   g_assert (EPHY_IS_SYNC_SERVICE (self));
 
+  /* To get the storage credentials from the Token Server, we need to create a
+   * BrowserID assertion. For that we need to obtain an identity certificate
+   * signed by the Firefox Accounts Server.
+   */
+
   /* Generate a new RSA key pair to sign the new certificate. */
-  if (self->rsa_key_pair)
-    ephy_sync_crypto_rsa_key_pair_free (self->rsa_key_pair);
-  self->rsa_key_pair = ephy_sync_crypto_generate_rsa_key_pair ();
+  if (self->key_pair)
+    ephy_sync_crypto_rsa_key_pair_free (self->key_pair);
+  self->key_pair = ephy_sync_crypto_rsa_key_pair_new ();
 
-  /* Derive tokenID, reqHMACkey and requestKey from sessionToken. */
+  /* Derive tokenID and reqHMACkey from sessionToken. */
   session_token = ephy_sync_service_get_secret (self, secrets[SESSION_TOKEN]);
-  ephy_sync_crypto_process_session_token (session_token, &token_id,
-                                          &req_hmac_key, &request_key, 32);
+  ephy_sync_crypto_derive_session_token (session_token, &token_id,
+                                         &req_hmac_key, &tmp);
   token_id_hex = ephy_sync_utils_encode_hex (token_id, 32);
 
-  n = mpz_get_str (NULL, 10, self->rsa_key_pair->public.n);
-  e = mpz_get_str (NULL, 10, self->rsa_key_pair->public.e);
+  n = mpz_get_str (NULL, 10, self->key_pair->public.n);
+  e = mpz_get_str (NULL, 10, self->key_pair->public.e);
   node = json_node_new (JSON_NODE_OBJECT);
   object_body = json_object_new ();
   /* Milliseconds, limited to 24 hours. */
@@ -946,9 +935,9 @@ ephy_sync_service_obtain_signed_certificate (EphySyncService *self)
   json_object_set_object_member (object_body, "publicKey", object_key);
   json_node_set_object (node, object_body);
   request_body = json_to_string (node, FALSE);
-  ephy_sync_service_fxa_hawk_post_async (self, "certificate/sign", token_id_hex,
-                                         req_hmac_key, 32, request_body,
-                                         obtain_signed_certificate_cb, self);
+  ephy_sync_service_fxa_hawk_post (self, "certificate/sign", token_id_hex,
+                                   req_hmac_key, 32, request_body,
+                                   get_signed_certificate_cb, self);
 
   g_free (request_body);
   json_object_unref (object_body);
@@ -956,7 +945,7 @@ ephy_sync_service_obtain_signed_certificate (EphySyncService *self)
   g_free (e);
   g_free (n);
   g_free (token_id_hex);
-  g_free (request_key);
+  g_free (tmp);
   g_free (req_hmac_key);
   g_free (token_id);
 }
@@ -983,17 +972,19 @@ ephy_sync_service_queue_storage_request (EphySyncService     *self,
 
   /* If the storage credentials are valid, then directly send the request.
    * Otherwise, the request will remain queued and scheduled to be sent when
-   * the new credentials are obtained. */
+   * the new credentials are obtained.
+   */
   if (!ephy_sync_service_storage_credentials_is_expired (self)) {
     ephy_sync_service_send_storage_request (self, data);
   } else {
     g_queue_push_tail (self->storage_queue, data);
     if (!self->locked) {
-      /* Mark as locked so other requests won't lead to conflicts while obtaining
-       * new storage credentials. */
+      /* Mark as locked so other requests won't lead to conflicts while
+       * obtaining new storage credentials.
+       */
       self->locked = TRUE;
       ephy_sync_service_clear_storage_credentials (self);
-      ephy_sync_service_obtain_signed_certificate (self);
+      ephy_sync_service_get_storage_credentials (self);
     }
   }
 }
@@ -1035,7 +1026,8 @@ ephy_sync_service_delete_synchronizable (EphySyncService           *self,
   collection = ephy_synchronizable_manager_get_collection_name (manager);
   id = ephy_synchronizable_get_id (synchronizable);
   /* Firefox uses UUIDs with curly braces as IDs for saved passwords records.
-   * Curly braces are unsafe characters in URLs so they must be encoded. */
+   * Curly braces are unsafe characters in URLs so they must be encoded.
+   */
   id_safe = soup_uri_encode (id, NULL);
   endpoint = g_strdup_printf ("storage/%s/%s", collection, id_safe);
 
@@ -1138,7 +1130,8 @@ ephy_sync_service_download_synchronizable (EphySyncService           *self,
   id = ephy_synchronizable_get_id (synchronizable);
   collection = ephy_synchronizable_manager_get_collection_name (manager);
   /* Firefox uses UUIDs with curly braces as IDs for saved passwords records.
-   * Curly braces are unsafe characters in URLs so they must be encoded. */
+   * Curly braces are unsafe characters in URLs so they must be encoded.
+   */
   id_safe = soup_uri_encode (id, NULL);
   endpoint = g_strdup_printf ("storage/%s/%s", collection, id_safe);
   data = sync_async_data_new (self, manager, synchronizable);
@@ -1160,8 +1153,9 @@ upload_synchronizable_cb (SoupSession *session,
   SyncAsyncData *data = (SyncAsyncData *)user_data;
   double time_modified;
 
-  /* Code 412 means that there is a more recent version of the object
-   * on the server. Download it. */
+  /* Code 412 means that there is a more recent version on the server.
+   * Download it.
+   */
   if (msg->status_code == 412) {
     LOG ("Found a newer version of the object on the server, downloading it...");
     ephy_sync_service_download_synchronizable (data->service, data->manager, data->synchronizable);
@@ -1204,7 +1198,8 @@ ephy_sync_service_upload_synchronizable (EphySyncService           *self,
   bso = ephy_synchronizable_to_bso (synchronizable, bundle);
   id = ephy_synchronizable_get_id (synchronizable);
   /* Firefox uses UUIDs with curly braces as IDs for saved passwords records.
-   * Curly braces are unsafe characters in URLs so they must be encoded. */
+   * Curly braces are unsafe characters in URLs so they must be encoded.
+   */
   id_safe = soup_uri_encode (id, NULL);
   endpoint = g_strdup_printf ("storage/%s/%s", collection, id_safe);
   data = sync_async_data_new (self, manager, synchronizable);
@@ -1351,9 +1346,8 @@ ephy_sync_service_sync_collection (EphySyncService           *self,
 }
 
 static gboolean
-ephy_sync_service_sync (gpointer user_data)
+ephy_sync_service_sync_internal (EphySyncService *self)
 {
-  EphySyncService *self = EPHY_SYNC_SERVICE (user_data);
   guint index = 0;
   guint num_managers;
 
@@ -1374,17 +1368,6 @@ ephy_sync_service_sync (gpointer user_data)
 }
 
 static void
-ephy_sync_service_stop_periodical_sync (EphySyncService *self)
-{
-  g_assert (EPHY_IS_SYNC_SERVICE (self));
-
-  if (self->source_id != 0) {
-    g_source_remove (self->source_id);
-    self->source_id = 0;
-  }
-}
-
-static void
 ephy_sync_service_schedule_periodical_sync (EphySyncService *self)
 {
   guint seconds;
@@ -1392,12 +1375,25 @@ ephy_sync_service_schedule_periodical_sync (EphySyncService *self)
   g_assert (EPHY_IS_SYNC_SERVICE (self));
 
   seconds = ephy_sync_utils_get_sync_frequency () * 60;
-  self->source_id = g_timeout_add_seconds (seconds, ephy_sync_service_sync, self);
+  self->source_id = g_timeout_add_seconds (seconds,
+                                          (GSourceFunc)ephy_sync_service_sync_internal,
+                                          self);
 
   LOG ("Scheduled new sync with frequency %u minutes", seconds / 60);
 }
 
 static void
+ephy_sync_service_stop_periodical_sync (EphySyncService *self)
+{
+  g_assert (EPHY_IS_SYNC_SERVICE (self));
+
+  if (self->source_id != 0) {
+    g_source_remove (self->source_id);
+    self->source_id = 0;
+  }
+}
+
+static void
 sync_frequency_changed_cb (GSettings       *settings,
                            char            *key,
                            EphySyncService *self)
@@ -1450,7 +1446,7 @@ load_secrets_cb (SecretService   *service,
                                   json_object_get_string_member (object, l->data));
 
   if (self->sync_periodically)
-    ephy_sync_service_start_periodical_sync (self);
+    ephy_sync_service_start_sync (self);
   goto out_no_error;
 
 out_error:
@@ -1565,7 +1561,7 @@ ephy_sync_service_dispose (GObject *object)
 
   ephy_sync_service_clear_storage_credentials (self);
   g_clear_object (&self->session);
-  g_clear_pointer (&self->rsa_key_pair, ephy_sync_crypto_rsa_key_pair_free);
+  g_clear_pointer (&self->key_pair, ephy_sync_crypto_rsa_key_pair_free);
   g_clear_pointer (&self->secrets, g_hash_table_destroy);
   g_clear_pointer (&self->managers, g_slist_free);
   g_queue_free_full (self->storage_queue, (GDestroyNotify)storage_request_async_data_free);
@@ -1656,7 +1652,7 @@ ephy_sync_service_new (gboolean sync_periodically)
 }
 
 static char *
-ephy_sync_service_upload_crypto_keys_record (EphySyncService *self)
+ephy_sync_service_upload_crypto_keys (EphySyncService *self)
 {
   SyncCryptoKeyBundle *bundle;
   JsonNode *node;
@@ -1664,18 +1660,18 @@ ephy_sync_service_upload_crypto_keys_record (EphySyncService *self)
   char *payload_clear;
   char *payload_cipher;
   char *body;
-  const char *master_key_hex;
-  guint8 *master_key;
+  const char *kb_hex;
+  guint8 *kb;
 
   g_assert (EPHY_IS_SYNC_SERVICE (self));
-  master_key_hex = ephy_sync_service_get_secret (self, secrets[MASTER_KEY]);
-  g_assert (master_key_hex);
+  kb_hex = ephy_sync_service_get_secret (self, secrets[MASTER_KEY]);
+  g_assert (kb_hex);
 
   node = json_node_new (JSON_NODE_OBJECT);
   record = json_object_new ();
-  payload_clear = ephy_sync_crypto_generate_crypto_keys (32);
-  master_key = ephy_sync_utils_decode_hex (master_key_hex);
-  bundle = ephy_sync_crypto_derive_key_bundle (master_key, 32);
+  payload_clear = ephy_sync_crypto_generate_crypto_keys ();
+  kb = ephy_sync_utils_decode_hex (kb_hex);
+  bundle = ephy_sync_crypto_derive_master_bundle (kb);
   payload_cipher = ephy_sync_crypto_encrypt_record (payload_clear, bundle);
   json_object_set_string_member (record, "payload", payload_cipher);
   json_object_set_string_member (record, "id", "keys");
@@ -1688,7 +1684,7 @@ ephy_sync_service_upload_crypto_keys_record (EphySyncService *self)
 
   g_free (body);
   g_free (payload_cipher);
-  g_free (master_key);
+  g_free (kb);
   json_object_unref (record);
   json_node_unref (node);
   ephy_sync_crypto_key_bundle_free (bundle);
@@ -1697,9 +1693,9 @@ ephy_sync_service_upload_crypto_keys_record (EphySyncService *self)
 }
 
 static void
-obtain_crypto_keys_cb (SoupSession *session,
-                       SoupMessage *msg,
-                       gpointer     user_data)
+get_crypto_keys_cb (SoupSession *session,
+                    SoupMessage *msg,
+                    gpointer     user_data)
 {
   EphySyncService *self = EPHY_SYNC_SERVICE (user_data);
   SyncCryptoKeyBundle *bundle = NULL;
@@ -1708,10 +1704,10 @@ obtain_crypto_keys_cb (SoupSession *session,
   GError *error = NULL;
   const char *payload;
   char *crypto_keys = NULL;
-  guint8 *key_b = NULL;
+  guint8 *kb = NULL;
 
   if (msg->status_code == 404) {
-    crypto_keys = ephy_sync_service_upload_crypto_keys_record (self);
+    crypto_keys = ephy_sync_service_upload_crypto_keys (self);
     goto store_secrets;
   }
 
@@ -1738,9 +1734,10 @@ obtain_crypto_keys_cb (SoupSession *session,
   }
   /* Derive the Sync Key bundle from kB. The bundle consists of two 32 bytes keys:
    * the first one used as a symmetric encryption key (AES) and the second one
-   * used as a HMAC key. */
-  key_b = ephy_sync_utils_decode_hex (ephy_sync_service_get_secret (self, secrets[MASTER_KEY]));
-  bundle = ephy_sync_crypto_derive_key_bundle (key_b, 32);
+   * used as a HMAC key.
+   */
+  kb = ephy_sync_utils_decode_hex (ephy_sync_service_get_secret (self, secrets[MASTER_KEY]));
+  bundle = ephy_sync_crypto_derive_master_bundle (kb);
   crypto_keys = ephy_sync_crypto_decrypt_record (payload, bundle);
   if (!crypto_keys) {
     g_warning ("Failed to decrypt crypto/keys record");
@@ -1762,17 +1759,17 @@ out_no_error:
   if (error)
     g_error_free (error);
   g_free (crypto_keys);
-  g_free (key_b);
+  g_free (kb);
 }
 
 static void
-ephy_sync_service_obtain_crypto_keys (EphySyncService *self)
+ephy_sync_service_get_crypto_keys (EphySyncService *self)
 {
   g_assert (EPHY_IS_SYNC_SERVICE (self));
 
   ephy_sync_service_queue_storage_request (self, "storage/crypto/keys",
                                            SOUP_METHOD_GET, NULL, -1, -1,
-                                           obtain_crypto_keys_cb, self);
+                                           get_crypto_keys_cb, self);
 }
 
 static JsonObject *
@@ -1792,7 +1789,7 @@ make_engine_object (int version)
 }
 
 static void
-ephy_sync_service_upload_meta_global_record (EphySyncService *self)
+ephy_sync_service_upload_meta_global (EphySyncService *self)
 {
   JsonNode *node;
   JsonObject *record;
@@ -1843,9 +1840,9 @@ ephy_sync_service_upload_meta_global_record (EphySyncService *self)
 }
 
 static void
-check_storage_version_cb (SoupSession *session,
-                          SoupMessage *msg,
-                          gpointer     user_data)
+verify_storage_version_cb (SoupSession *session,
+                           SoupMessage *msg,
+                           gpointer     user_data)
 {
   EphySyncService *self = EPHY_SYNC_SERVICE (user_data);
   JsonParser *parser = NULL;
@@ -1856,7 +1853,7 @@ check_storage_version_cb (SoupSession *session,
   int storage_version;
 
   if (msg->status_code == 404) {
-    ephy_sync_service_upload_meta_global_record (self);
+    ephy_sync_service_upload_meta_global (self);
     goto obtain_crypto_keys;
   }
 
@@ -1907,7 +1904,7 @@ check_storage_version_cb (SoupSession *session,
   }
 
 obtain_crypto_keys:
-  ephy_sync_service_obtain_crypto_keys (self);
+  ephy_sync_service_get_crypto_keys (self);
   goto out_no_error;
 out_error:
   message = message ? message : _("Failed to verify storage version.");
@@ -1922,34 +1919,34 @@ out_no_error:
 }
 
 static void
-ephy_sync_service_check_storage_version (EphySyncService *self)
+ephy_sync_service_verify_storage_version (EphySyncService *self)
 {
   g_assert (EPHY_IS_SYNC_SERVICE (self));
 
   ephy_sync_service_queue_storage_request (self, "storage/meta/global",
                                            SOUP_METHOD_GET, NULL, -1, -1,
-                                           check_storage_version_cb, self);
+                                           verify_storage_version_cb, self);
 }
 
 static void
-ephy_sync_service_conclude_sign_in (EphySyncService *self,
-                                    SignInAsyncData *data,
-                                    const char      *bundle)
+ephy_sync_service_sign_in_finish (EphySyncService *self,
+                                  SignInAsyncData *data,
+                                  const char      *bundle)
 {
-  guint8 *unwrap_key_b;
-  guint8 *key_a;
-  guint8 *key_b;
-  char *key_b_hex;
+  guint8 *unwrap_kb;
+  guint8 *ka;
+  guint8 *kb;
+  char *kb_hex;
 
   g_assert (EPHY_IS_SYNC_SERVICE (self));
   g_assert (data);
   g_assert (bundle);
 
   /* Derive the master sync keys form the key bundle. */
-  unwrap_key_b = ephy_sync_utils_decode_hex (data->unwrap_b_key);
-  if (!ephy_sync_crypto_compute_sync_keys (bundle, data->resp_hmac_key,
-                                           data->resp_xor_key, unwrap_key_b,
-                                           &key_a, &key_b, 32)) {
+  unwrap_kb = ephy_sync_utils_decode_hex (data->unwrap_kb);
+  if (!ephy_sync_crypto_derive_master_keys (bundle, data->resp_hmac_key,
+                                            data->resp_xor_key, unwrap_kb,
+                                            &ka, &kb)) {
     ephy_sync_service_report_sign_in_error (self, _("Failed to retrieve the Sync Key"),
                                             data->session_token, FALSE);
     goto out;
@@ -1966,16 +1963,16 @@ ephy_sync_service_conclude_sign_in (EphySyncService *self,
   self->user = g_strdup (data->email);
   ephy_sync_service_set_secret (self, secrets[UID], data->uid);
   ephy_sync_service_set_secret (self, secrets[SESSION_TOKEN], data->session_token);
-  key_b_hex = ephy_sync_utils_encode_hex (key_b, 32);
-  ephy_sync_service_set_secret (self, secrets[MASTER_KEY], key_b_hex);
+  kb_hex = ephy_sync_utils_encode_hex (kb, 32);
+  ephy_sync_service_set_secret (self, secrets[MASTER_KEY], kb_hex);
 
-  ephy_sync_service_check_storage_version (self);
+  ephy_sync_service_verify_storage_version (self);
 
-  g_free (key_b_hex);
-  g_free (key_b);
-  g_free (key_a);
+  g_free (kb_hex);
+  g_free (kb);
+  g_free (ka);
 out:
-  g_free (unwrap_key_b);
+  g_free (unwrap_kb);
   sign_in_async_data_free (data);
 }
 
@@ -2008,17 +2005,18 @@ get_account_keys_cb (SoupSession *session,
       goto out_error;
     }
     /* Extract the master sync keys from the bundle and save tokens. */
-    ephy_sync_service_conclude_sign_in (data->service, data, bundle);
+    ephy_sync_service_sign_in_finish (data->service, data, bundle);
     goto out_no_error;
   }
 
-  /* If account is not verified, poll the Firefox Accounts Server until the
-   * verification has completed. */
+  /* If account is not verified, poll the Firefox Accounts Server
+   * until the verification has completed.
+   */
   if (json_object_get_int_member (json, "errno") == 104) {
     LOG ("Account not verified, retrying...");
-    ephy_sync_service_fxa_hawk_get_async (data->service, "account/keys",
-                                          data->token_id_hex, data->req_hmac_key,
-                                          32, get_account_keys_cb, data);
+    ephy_sync_service_fxa_hawk_get (data->service, "account/keys",
+                                    data->token_id_hex, data->req_hmac_key, 32,
+                                    get_account_keys_cb, data);
     goto out_no_error;
   }
 
@@ -2038,12 +2036,12 @@ out_no_error:
 }
 
 void
-ephy_sync_service_do_sign_in (EphySyncService *self,
-                              const char      *email,
-                              const char      *uid,
-                              const char      *session_token,
-                              const char      *key_fetch_token,
-                              const char      *unwrap_b_key)
+ephy_sync_service_sign_in (EphySyncService *self,
+                           const char      *email,
+                           const char      *uid,
+                           const char      *session_token,
+                           const char      *key_fetch_token,
+                           const char      *unwrap_kb)
 {
   SignInAsyncData *data;
   guint8 *token_id;
@@ -2057,27 +2055,29 @@ ephy_sync_service_do_sign_in (EphySyncService *self,
   g_return_if_fail (uid);
   g_return_if_fail (session_token);
   g_return_if_fail (key_fetch_token);
-  g_return_if_fail (unwrap_b_key);
+  g_return_if_fail (unwrap_kb);
 
   self->is_signing_in = TRUE;
 
   /* Derive tokenID, reqHMACkey, respHMACkey and respXORkey from keyFetchToken.
-   * tokenID and reqHMACkey are used to sign a HAWK GET requests to the /account/keys
+   * tokenID and reqHMACkey are used to sign HAWK GET requests to /account/keys
    * endpoint. The server looks up the stored table entry with tokenID, checks
    * the request HMAC for validity, then returns the pre-encrypted response.
-   * See https://github.com/mozilla/fxa-auth-server/wiki/onepw-protocol#fetching-sync-keys */
-  ephy_sync_crypto_process_key_fetch_token (key_fetch_token, &token_id, &req_hmac_key,
-                                            &resp_hmac_key, &resp_xor_key, 32);
+   * See https://github.com/mozilla/fxa-auth-server/wiki/onepw-protocol#fetching-sync-keys
+   */
+  ephy_sync_crypto_derive_key_fetch_token (key_fetch_token,
+                                           &token_id, &req_hmac_key,
+                                           &resp_hmac_key, &resp_xor_key);
   token_id_hex = ephy_sync_utils_encode_hex (token_id, 32);
 
   /* Get the master sync key bundle from the /account/keys endpoint. */
   data = sign_in_async_data_new (self, email, uid,
-                                 session_token, unwrap_b_key,
+                                 session_token, unwrap_kb,
                                  token_id_hex, req_hmac_key,
                                  resp_hmac_key, resp_xor_key);
-  ephy_sync_service_fxa_hawk_get_async (self, "account/keys", token_id_hex,
-                                        req_hmac_key, 32,
-                                        get_account_keys_cb, data);
+  ephy_sync_service_fxa_hawk_get (self, "account/keys",
+                                  token_id_hex, req_hmac_key, 32,
+                                  get_account_keys_cb, data);
 
   g_free (token_id_hex);
   g_free (token_id);
@@ -2295,7 +2295,7 @@ ephy_sync_service_unregister_device (EphySyncService *self)
 }
 
 void
-ephy_sync_service_do_sign_out (EphySyncService *self)
+ephy_sync_service_sign_out (EphySyncService *self)
 {
   g_return_if_fail (EPHY_IS_SYNC_SERVICE (self));
 
@@ -2316,21 +2316,21 @@ ephy_sync_service_do_sign_out (EphySyncService *self)
 }
 
 void
-ephy_sync_service_do_sync (EphySyncService *self)
+ephy_sync_service_sync (EphySyncService *self)
 {
   g_return_if_fail (EPHY_IS_SYNC_SERVICE (self));
   g_return_if_fail (ephy_sync_utils_user_is_signed_in ());
 
-  ephy_sync_service_sync (self);
+  ephy_sync_service_sync_internal (self);
 }
 
 void
-ephy_sync_service_start_periodical_sync (EphySyncService *self)
+ephy_sync_service_start_sync (EphySyncService *self)
 {
   g_return_if_fail (EPHY_IS_SYNC_SERVICE (self));
   g_return_if_fail (ephy_sync_utils_user_is_signed_in ());
   g_return_if_fail (self->sync_periodically);
 
-  ephy_sync_service_sync (self);
+  ephy_sync_service_sync_internal (self);
   ephy_sync_service_schedule_periodical_sync (self);
 }
diff --git a/lib/sync/ephy-sync-service.h b/lib/sync/ephy-sync-service.h
index 3fdba70..4668e13 100644
--- a/lib/sync/ephy-sync-service.h
+++ b/lib/sync/ephy-sync-service.h
@@ -30,21 +30,21 @@ G_BEGIN_DECLS
 
 G_DECLARE_FINAL_TYPE (EphySyncService, ephy_sync_service, EPHY, SYNC_SERVICE, GObject)
 
-EphySyncService *ephy_sync_service_new                    (gboolean sync_periodically);
-void             ephy_sync_service_do_sign_in             (EphySyncService *self,
-                                                           const char      *email,
-                                                           const char      *uid,
-                                                           const char      *session_token,
-                                                           const char      *key_fetch_token,
-                                                           const char      *unwrap_b_key);
-void             ephy_sync_service_do_sign_out            (EphySyncService *self);
-void             ephy_sync_service_do_sync                (EphySyncService *self);
-void             ephy_sync_service_start_periodical_sync  (EphySyncService *self);
-void             ephy_sync_service_register_device        (EphySyncService *self,
-                                                           const char      *device_name);
-void             ephy_sync_service_register_manager       (EphySyncService           *self,
-                                                           EphySynchronizableManager *manager);
-void             ephy_sync_service_unregister_manager     (EphySyncService           *self,
-                                                           EphySynchronizableManager *manager);
+EphySyncService *ephy_sync_service_new                (gboolean sync_periodically);
+void             ephy_sync_service_sign_in            (EphySyncService *self,
+                                                       const char      *email,
+                                                       const char      *uid,
+                                                       const char      *session_token,
+                                                       const char      *key_fetch_token,
+                                                       const char      *unwrap_kb);
+void             ephy_sync_service_sign_out           (EphySyncService *self);
+void             ephy_sync_service_sync               (EphySyncService *self);
+void             ephy_sync_service_start_sync         (EphySyncService *self);
+void             ephy_sync_service_register_device    (EphySyncService *self,
+                                                       const char      *device_name);
+void             ephy_sync_service_register_manager   (EphySyncService           *self,
+                                                       EphySynchronizableManager *manager);
+void             ephy_sync_service_unregister_manager (EphySyncService           *self,
+                                                       EphySynchronizableManager *manager);
 
 G_END_DECLS
diff --git a/src/prefs-dialog.c b/src/prefs-dialog.c
index 49b7019..b458d15 100644
--- a/src/prefs-dialog.c
+++ b/src/prefs-dialog.c
@@ -181,7 +181,7 @@ prefs_dialog_finalize (GObject *object)
 
   if (dialog->sync_service != NULL) {
     if (ephy_sync_utils_user_is_signed_in () && !dialog->sync_was_signed_in)
-      ephy_sync_service_start_periodical_sync (dialog->sync_service);
+      ephy_sync_service_start_sync (dialog->sync_service);
   }
 
   G_OBJECT_CLASS (prefs_dialog_parent_class)->finalize (object);
@@ -400,7 +400,7 @@ sync_fxa_server_message_cb (WebKitUserContentManager *manager,
   const char *uid;
   const char *session_token;
   const char *key_fetch_token;
-  const char *unwrap_b_key;
+  const char *unwrap_kb;
 
   json_string = ephy_embed_utils_get_js_result_as_string (result);
   if (!json_string) {
@@ -476,8 +476,8 @@ sync_fxa_server_message_cb (WebKitUserContentManager *manager,
   uid = json_object_get_string_member (data, "uid");
   session_token = json_object_get_string_member (data, "sessionToken");
   key_fetch_token = json_object_get_string_member (data, "keyFetchToken");
-  unwrap_b_key = json_object_get_string_member (data, "unwrapBKey");
-  if (!email || !uid || !session_token || !key_fetch_token || !unwrap_b_key) {
+  unwrap_kb = json_object_get_string_member (data, "unwrapBKey");
+  if (!email || !uid || !session_token || !key_fetch_token || !unwrap_kb) {
     g_warning ("JSON object has missing or invalid members");
     goto out_error;
   }
@@ -490,8 +490,8 @@ sync_fxa_server_message_cb (WebKitUserContentManager *manager,
   if (!json_object_get_boolean_member (data, "verified"))
     sync_sign_in_details_show (dialog, _("Please don’t leave this page until "
                                          "you have completed the verification."));
-  ephy_sync_service_do_sign_in (dialog->sync_service, email, uid,
-                                session_token, key_fetch_token, unwrap_b_key);
+  ephy_sync_service_sign_in (dialog->sync_service, email, uid,
+                             session_token, key_fetch_token, unwrap_kb);
   goto out_no_error;
 
 out_error:
@@ -561,7 +561,7 @@ on_sync_sign_out_button_clicked (GtkWidget   *button,
                                  PrefsDialog *dialog)
 {
 
-  ephy_sync_service_do_sign_out (dialog->sync_service);
+  ephy_sync_service_sign_out (dialog->sync_service);
 
   /* Show Firefox Accounts iframe. */
   sync_setup_firefox_iframe (dialog);
@@ -582,7 +582,7 @@ on_sync_sync_now_button_clicked (GtkWidget   *button,
                                  PrefsDialog *dialog)
 {
   gtk_widget_set_sensitive (button, FALSE);
-  ephy_sync_service_do_sync (dialog->sync_service);
+  ephy_sync_service_sync (dialog->sync_service);
 }
 
 static void


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