[epiphany/wip/ephy-sync: 30/52] Implement sign certificate act



commit 0d441056e6d150231c5d49391f512f2ac1ecb47b
Author: Gabriel Ivascu <ivascu gabriel59 gmail com>
Date:   Mon Jul 18 23:22:17 2016 +0300

    Implement sign certificate act

 src/ephy-sync-crypto.c  |   60 ++++++++++++++++++++++++
 src/ephy-sync-crypto.h  |   10 ++++
 src/ephy-sync-service.c |  115 +++++++++++++++++++++++++++++++++++++++++++++++
 src/ephy-sync-service.h |    2 +
 4 files changed, 187 insertions(+), 0 deletions(-)
---
diff --git a/src/ephy-sync-crypto.c b/src/ephy-sync-crypto.c
index 37a9743..50c1584 100644
--- a/src/ephy-sync-crypto.c
+++ b/src/ephy-sync-crypto.c
@@ -142,6 +142,19 @@ ephy_sync_crypto_sync_keys_new (guint8 *kA,
   return sync_keys;
 }
 
+static EphySyncCryptoRSAKeyPair *
+ephy_sync_crypto_rsa_key_pair_new (struct rsa_public_key  public_key,
+                                   struct rsa_private_key private_key)
+{
+  EphySyncCryptoRSAKeyPair *key_pair;
+
+  key_pair = g_slice_new (EphySyncCryptoRSAKeyPair);
+  key_pair->public_key = public_key;
+  key_pair->private_key = private_key;
+
+  return key_pair;
+}
+
 void
 ephy_sync_crypto_hawk_options_free (EphySyncCryptoHawkOptions *hawk_options)
 {
@@ -227,6 +240,17 @@ ephy_sync_crypto_sync_keys_free (EphySyncCryptoSyncKeys *sync_keys)
   g_slice_free (EphySyncCryptoSyncKeys, sync_keys);
 }
 
+void
+ephy_sync_crypto_rsa_key_pair_free (EphySyncCryptoRSAKeyPair *key_pair)
+{
+  g_return_if_fail (key_pair != NULL);
+
+  rsa_public_key_clear (&key_pair->public_key);
+  rsa_private_key_clear (&key_pair->private_key);
+
+  g_slice_free (EphySyncCryptoRSAKeyPair, key_pair);
+}
+
 static guint8 *
 xor (guint8 *a,
      guint8 *b,
@@ -524,6 +548,15 @@ hkdf (guint8 *in,
   g_free (prk);
 }
 
+static void
+random_func (void   *ctx,
+             gsize   length,
+             guint8 *dst)
+{
+  for (gsize i = 0; i < length; i++)
+    dst[i] = g_random_int ();
+}
+
 EphySyncCryptoProcessedKFT *
 ephy_sync_crypto_process_key_fetch_token (const gchar *keyFetchToken)
 {
@@ -765,3 +798,30 @@ ephy_sync_crypto_compute_hawk_header (const gchar               *url,
 
   return ephy_sync_crypto_hawk_header_new (header, artifacts);
 }
+
+EphySyncCryptoRSAKeyPair *
+ephy_sync_crypto_generate_rsa_key_pair (void)
+{
+  struct rsa_public_key public;
+  struct rsa_private_key private;
+  gint retval;
+
+  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 */
+  retval = rsa_generate_keypair (&public, &private,
+                                 NULL, random_func,
+                                 NULL, NULL, 2048, 0);
+  if (retval == 0) {
+    g_warning ("Failed to generate RSA key pair");
+    rsa_public_key_clear (&public);
+    rsa_private_key_clear (&private);
+    return NULL;
+  }
+
+  return ephy_sync_crypto_rsa_key_pair_new (public, private);
+}
diff --git a/src/ephy-sync-crypto.h b/src/ephy-sync-crypto.h
index 33846ad..545eaa2 100644
--- a/src/ephy-sync-crypto.h
+++ b/src/ephy-sync-crypto.h
@@ -20,6 +20,7 @@
 #define EPHY_SYNC_CRYPTO_H
 
 #include <glib-object.h>
+#include <nettle/rsa.h>
 
 G_BEGIN_DECLS
 
@@ -72,6 +73,11 @@ typedef struct {
   guint8 *wrapKB;
 } EphySyncCryptoSyncKeys;
 
+typedef struct {
+  struct rsa_public_key public_key;
+  struct rsa_private_key private_key;
+} EphySyncCryptoRSAKeyPair;
+
 EphySyncCryptoHawkOptions   *ephy_sync_crypto_hawk_options_new       (gchar *app,
                                                                       gchar *dlg,
                                                                       gchar *ext,
@@ -92,6 +98,8 @@ void                        ephy_sync_crypto_processed_st_free       (EphySyncCr
 
 void                        ephy_sync_crypto_sync_keys_free          (EphySyncCryptoSyncKeys *sync_keys);
 
+void                        ephy_sync_crypto_rsa_key_pair_free       (EphySyncCryptoRSAKeyPair *key_pair);
+
 EphySyncCryptoProcessedKFT *ephy_sync_crypto_process_key_fetch_token (const gchar *keyFetchToken);
 
 EphySyncCryptoProcessedST  *ephy_sync_crypto_process_session_token   (const gchar *sessionToken);
@@ -108,6 +116,8 @@ EphySyncCryptoHawkHeader   *ephy_sync_crypto_compute_hawk_header     (const gcha
                                                                       gsize                      key_length,
                                                                       EphySyncCryptoHawkOptions *options);
 
+EphySyncCryptoRSAKeyPair   *ephy_sync_crypto_generate_rsa_key_pair   (void);
+
 G_END_DECLS
 
 #endif
diff --git a/src/ephy-sync-service.c b/src/ephy-sync-service.c
index 9077a84..d4b78c2 100644
--- a/src/ephy-sync-service.c
+++ b/src/ephy-sync-service.c
@@ -46,6 +46,59 @@ struct _EphySyncService {
 G_DEFINE_TYPE (EphySyncService, ephy_sync_service, G_TYPE_OBJECT);
 
 static guint
+synchronous_hawk_post_request (EphySyncService  *self,
+                              const gchar      *endpoint,
+                              const gchar      *id,
+                              guint8           *key,
+                              gsize             key_length,
+                              gchar            *request_body,
+                              JsonObject      **jobject)
+{
+  EphySyncCryptoHawkOptions *hawk_options;
+  EphySyncCryptoHawkHeader *hawk_header;
+  SoupMessage *message;
+  JsonNode *root;
+  gchar *url;
+  const gchar *content_type = "application/json";
+
+  url = g_strdup_printf ("%s%s%s", FXA_BASEURL, FXA_VERSION, endpoint);
+  message = soup_message_new (SOUP_METHOD_POST, url);
+  soup_message_set_request (message, content_type,
+                            SOUP_MEMORY_COPY,
+                            request_body, strlen (request_body));
+
+  hawk_options = ephy_sync_crypto_hawk_options_new (NULL, NULL, NULL,
+                                                    g_strdup (content_type),
+                                                    NULL, NULL, NULL,
+                                                    g_strdup (request_body),
+                                                    NULL);
+  hawk_header = ephy_sync_crypto_compute_hawk_header (url, "POST",
+                                                      id,
+                                                      key, key_length,
+                                                      hawk_options);
+  soup_message_headers_append (message->request_headers,
+                               "authorization", hawk_header->header);
+  soup_message_headers_append (message->request_headers,
+                               "content-type", content_type);
+  soup_session_send_message (self->soup_session, message);
+
+  if (jobject != NULL) {
+    json_parser_load_from_data (self->parser,
+                                message->response_body->data,
+                                -1, NULL);
+    root = json_parser_get_root (self->parser);
+    g_assert (JSON_NODE_HOLDS_OBJECT (root));
+    *jobject = json_node_get_object (root);
+  }
+
+  g_free (url);
+  ephy_sync_crypto_hawk_options_free (hawk_options);
+  ephy_sync_crypto_hawk_header_free (hawk_header);
+
+  return message->status_code;
+}
+
+static guint
 synchronous_hawk_get_request (EphySyncService  *self,
                               const gchar      *endpoint,
                               const gchar      *id,
@@ -342,3 +395,65 @@ out:
 
   return retval;
 }
+
+const gchar *
+ephy_sync_service_sign_certificate (EphySyncService *self)
+{
+  EphySyncCryptoProcessedST *processed_st;
+  EphySyncCryptoRSAKeyPair *kpair;
+  JsonObject *jobject;
+  gchar *sessionToken;
+  gchar *tokenID;
+  gchar *public_key_json;
+  gchar *request_body;
+  gchar *n_str;
+  gchar *e_str;
+  guint status_code;
+  const gchar *certificate = NULL;
+
+  sessionToken = ephy_sync_service_get_token (self, EPHY_SYNC_TOKEN_SESSIONTOKEN);
+  g_return_val_if_fail (sessionToken != NULL, NULL);
+
+  kpair = ephy_sync_crypto_generate_rsa_key_pair ();
+  g_return_val_if_fail (kpair != NULL, NULL);
+
+  processed_st = ephy_sync_crypto_process_session_token (sessionToken);
+  tokenID = ephy_sync_utils_encode_hex (processed_st->tokenID, 0);
+
+  n_str = mpz_get_str (NULL, 10, kpair->public_key.n);
+  e_str = mpz_get_str (NULL, 10, kpair->public_key.e);
+  public_key_json = ephy_sync_utils_build_json_string ("algorithm", "RS",
+                                                       "n", n_str,
+                                                       "e", e_str,
+                                                       NULL);
+  /* The server allows a maximum certificate lifespan of 24 hours == 86400000 ms */
+  request_body = g_strdup_printf ("{\"publicKey\": %s, \"duration\": 86400000}",
+                                  public_key_json);
+  status_code = synchronous_hawk_post_request (self,
+                                               "certificate/sign",
+                                               tokenID,
+                                               processed_st->reqHMACkey,
+                                               EPHY_SYNC_TOKEN_LENGTH,
+                                               request_body,
+                                               &jobject);
+
+  if (status_code != STATUS_OK) {
+    g_warning ("FxA server errno: %ld, errmsg: %s",
+               json_object_get_int_member (jobject, "errno"),
+               json_object_get_string_member (jobject, "message"));
+    goto out;
+  }
+
+  certificate = json_object_get_string_member (jobject, "cert");
+
+out:
+  ephy_sync_crypto_processed_st_free (processed_st);
+  ephy_sync_crypto_rsa_key_pair_free (kpair);
+  g_free (tokenID);
+  g_free (public_key_json);
+  g_free (request_body);
+  g_free (n_str);
+  g_free (e_str);
+
+  return certificate;
+}
diff --git a/src/ephy-sync-service.h b/src/ephy-sync-service.h
index 17054b6..9e78a4d 100644
--- a/src/ephy-sync-service.h
+++ b/src/ephy-sync-service.h
@@ -58,6 +58,8 @@ gboolean         ephy_sync_service_fetch_sync_keys      (EphySyncService *self,
                                                          const gchar     *keyFetchToken,
                                                          const gchar     *unwrapBKey);
 
+const gchar     *ephy_sync_service_sign_certificate     (EphySyncService *self);
+
 G_END_DECLS
 
 #endif


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