gnunet-svn
[Top][All Lists]
Advanced

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

[gnunet] 01/04: additional abstraction for identity keys


From: gnunet
Subject: [gnunet] 01/04: additional abstraction for identity keys
Date: Sat, 07 Nov 2020 10:39:53 +0100

This is an automated email from the git hooks/post-receive script.

thejackimonster pushed a commit to branch master
in repository gnunet.

commit c07ae5c8d29202466f066e4dcddbfd091513db7c
Author: TheJackiMonster <thejackimonster@gmail.com>
AuthorDate: Thu Nov 5 21:20:38 2020 +0100

    additional abstraction for identity keys
    
    Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
---
 src/conversation/conversation.h                |   2 +-
 src/conversation/gnunet-service-conversation.c |   8 +-
 src/gnsrecord/gnsrecord_misc.c                 |  11 +-
 src/identity/identity_api.c                    | 164 +++++++++++++++++++
 src/include/gnunet_identity_service.h          | 215 +++++++++++++++++++++++++
 5 files changed, 389 insertions(+), 11 deletions(-)

diff --git a/src/conversation/conversation.h b/src/conversation/conversation.h
index 9eedbeb91..d244f5163 100644
--- a/src/conversation/conversation.h
+++ b/src/conversation/conversation.h
@@ -313,7 +313,7 @@ struct CadetPhoneRingMessage
   /**
    * Signature over a `struct CadetPhoneRingInfoPS`
    */
-  struct GNUNET_CRYPTO_EcdsaSignature signature;
+  struct GNUNET_IDENTITY_Signature signature;
 };
 
 
diff --git a/src/conversation/gnunet-service-conversation.c 
b/src/conversation/gnunet-service-conversation.c
index b1a629217..5c8b573a2 100644
--- a/src/conversation/gnunet-service-conversation.c
+++ b/src/conversation/gnunet-service-conversation.c
@@ -752,10 +752,10 @@ handle_cadet_ring_message (void *cls, const struct 
CadetPhoneRingMessage *msg)
   rs.expiration_time = msg->expiration_time;
 
   if (GNUNET_OK !=
-      GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING,
+      GNUNET_IDENTITY_public_key_verify 
(GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING,
                                   &rs,
                                   &msg->signature,
-                                  &msg->caller_id.ecdsa_key))
+                                  &msg->caller_id))
   {
     GNUNET_break_op (0);
     destroy_line_cadet_channels (ch);
@@ -1138,9 +1138,7 @@ handle_client_call_message (void *cls, const struct 
ClientCallMessage *msg)
   e = GNUNET_MQ_msg (ring, GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RING);
   GNUNET_IDENTITY_key_get_public (&msg->caller_id, &ring->caller_id);
   ring->expiration_time = rs.expiration_time;
-  GNUNET_CRYPTO_ecdsa_sign (&msg->caller_id.ecdsa_key,
-                            &rs,
-                            &ring->signature);
+  GNUNET_IDENTITY_private_key_sign(&msg->caller_id, &rs, &ring->signature);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending RING message via CADET\n");
   GNUNET_MQ_send (ch->mq, e);
   GNUNET_SERVICE_client_continue (line->client);
diff --git a/src/gnsrecord/gnsrecord_misc.c b/src/gnsrecord/gnsrecord_misc.c
index ba8803850..2e00141a3 100644
--- a/src/gnsrecord/gnsrecord_misc.c
+++ b/src/gnsrecord/gnsrecord_misc.c
@@ -282,9 +282,9 @@ GNUNET_GNSRECORD_identity_from_data (const char *data,
     return GNUNET_SYSERR;
   if (data_size > sizeof (struct GNUNET_IDENTITY_PublicKey))
     return GNUNET_SYSERR;
-  key->type = type;
-  memcpy (key, data, data_size);
-  return GNUNET_OK;
+  return (GNUNET_IDENTITY_read_key_from_buffer(key, data, data_size) == 
data_size?
+                 GNUNET_OK :
+                 GNUNET_SYSERR);
 }
 
 enum GNUNET_GenericReturnValue
@@ -299,8 +299,9 @@ GNUNET_GNSRECORD_data_from_identity (const struct
   if (0 == *data_size)
     return GNUNET_SYSERR;
   *data = GNUNET_malloc (*data_size);
-  memcpy (*data, key, *data_size);
-  return GNUNET_OK;
+  return (GNUNET_IDENTITY_write_key_to_buffer(key, data, *data_size) == 
*data_size?
+                 GNUNET_OK :
+                 GNUNET_SYSERR);
 }
 
 
diff --git a/src/identity/identity_api.c b/src/identity/identity_api.c
index 213b6966e..242527c23 100644
--- a/src/identity/identity_api.c
+++ b/src/identity/identity_api.c
@@ -990,6 +990,170 @@ GNUNET_IDENTITY_key_get_length (const struct 
GNUNET_IDENTITY_PublicKey *key)
 }
 
 
+ssize_t
+GNUNET_IDENTITY_signature_get_length (const struct GNUNET_IDENTITY_Signature 
*sig)
+{
+  switch (ntohl (sig->type))
+  {
+  case GNUNET_IDENTITY_TYPE_ECDSA:
+       return sizeof (sig->type) + sizeof (sig->ecdsa_signature);
+       break;
+  case GNUNET_IDENTITY_TYPE_EDDSA:
+       return sizeof (sig->type) + sizeof (sig->eddsa_signature);
+       break;
+  default:
+       GNUNET_break (0);
+  }
+  return -1;
+}
+
+
+ssize_t
+GNUNET_IDENTITY_read_key_from_buffer (struct GNUNET_IDENTITY_PublicKey *key,
+                                      const void* buffer,
+                                                                         
size_t len)
+{
+  if (len < sizeof (key->type))
+    return -1;
+  GNUNET_memcpy(& (key->type), buffer, sizeof (key->type));
+  const ssize_t length = GNUNET_IDENTITY_key_get_length(key);
+  if (len < length)
+         return -1;
+  if (length < 0)
+    return -2;
+  GNUNET_memcpy(key, buffer, length);
+  return length;
+}
+
+
+ssize_t
+GNUNET_IDENTITY_write_key_to_buffer (const struct GNUNET_IDENTITY_PublicKey 
*key,
+                                     void* buffer,
+                                                                        size_t 
len)
+{
+  const ssize_t length = GNUNET_IDENTITY_key_get_length(key);
+  if (len < length)
+         return -1;
+  if (length < 0)
+       return -2;
+  GNUNET_memcpy(buffer, key, length);
+  return length;
+}
+
+
+int
+GNUNET_IDENTITY_private_key_sign_ (const struct GNUNET_IDENTITY_PrivateKey 
*priv,
+                                          const struct 
GNUNET_CRYPTO_EccSignaturePurpose *purpose,
+                                                                  struct 
GNUNET_IDENTITY_Signature *sig)
+{
+  sig->type = priv->type;
+  switch (ntohl (priv->type))
+  {
+  case GNUNET_IDENTITY_TYPE_ECDSA:
+       return GNUNET_CRYPTO_ecdsa_sign_ (& (priv->ecdsa_key), purpose, & 
(sig->ecdsa_signature));
+       break;
+  case GNUNET_IDENTITY_TYPE_EDDSA:
+       return GNUNET_CRYPTO_eddsa_sign_ (& (priv->eddsa_key), purpose, & 
(sig->eddsa_signature));
+       break;
+  default:
+       GNUNET_break (0);
+  }
+
+  return GNUNET_SYSERR;
+}
+
+
+int
+GNUNET_IDENTITY_public_key_verify_ (uint32_t purpose,
+                                           const struct 
GNUNET_CRYPTO_EccSignaturePurpose *validate,
+                                                                   const 
struct GNUNET_IDENTITY_Signature *sig,
+                                                                   const 
struct GNUNET_IDENTITY_PublicKey *pub)
+{
+  /* check type matching of 'sig' and 'pub' */
+  GNUNET_assert (ntohl (pub->type) == ntohl (sig->type));
+  switch (ntohl (pub->type))
+  {
+  case GNUNET_IDENTITY_TYPE_ECDSA:
+       return GNUNET_CRYPTO_ecdsa_verify_ (purpose, validate, & 
(sig->ecdsa_signature), & (pub->ecdsa_key));
+       break;
+  case GNUNET_IDENTITY_TYPE_EDDSA:
+       return GNUNET_CRYPTO_eddsa_verify_ (purpose, validate, & 
(sig->eddsa_signature), & (pub->eddsa_key));
+       break;
+  default:
+       GNUNET_break (0);
+  }
+
+  return GNUNET_SYSERR;
+}
+
+
+ssize_t
+GNUNET_IDENTITY_public_key_encrypt(const void *block,
+                                   size_t size,
+                                   const struct GNUNET_IDENTITY_PublicKey *pub,
+                                                                  struct 
GNUNET_CRYPTO_EcdhePublicKey *ecc,
+                                                                  void *result)
+{
+  struct GNUNET_CRYPTO_EcdhePrivateKey pk;
+  GNUNET_CRYPTO_ecdhe_key_create(&pk);
+  struct GNUNET_HashCode hash;
+  switch (ntohl (pub->type))
+  {
+  case GNUNET_IDENTITY_TYPE_ECDSA:
+    if (GNUNET_CRYPTO_ecdh_ecdsa(&pk, &(pub->ecdsa_key), &hash) == 
GNUNET_SYSERR)
+      return -1;
+    break;
+  case GNUNET_IDENTITY_TYPE_EDDSA:
+    if (GNUNET_CRYPTO_ecdh_eddsa(&pk, &(pub->eddsa_key), &hash) == 
GNUNET_SYSERR)
+      return -1;
+    break;
+  default:
+    return -1;
+  }
+  GNUNET_CRYPTO_ecdhe_key_get_public(&pk, ecc);
+  GNUNET_CRYPTO_ecdhe_key_clear(&pk);
+  struct GNUNET_CRYPTO_SymmetricSessionKey key;
+  struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
+  GNUNET_CRYPTO_hash_to_aes_key(&hash, &key, &iv);
+  GNUNET_CRYPTO_zero_keys(&hash, sizeof(hash));
+  const ssize_t encrypted = GNUNET_CRYPTO_symmetric_encrypt(block, size, &key, 
&iv, result);
+  GNUNET_CRYPTO_zero_keys(&key, sizeof(key));
+  GNUNET_CRYPTO_zero_keys(&iv, sizeof(iv));
+  return encrypted;
+}
+
+
+ssize_t
+GNUNET_IDENTITY_private_key_decrypt(const void *block,
+                                    size_t size,
+                                    const struct GNUNET_IDENTITY_PrivateKey 
*priv,
+                                                                       const 
struct GNUNET_CRYPTO_EcdhePublicKey *ecc,
+                                                                   void 
*result) {
+  struct GNUNET_HashCode hash;
+  switch (ntohl (priv->type))
+  {
+  case GNUNET_IDENTITY_TYPE_ECDSA:
+       if (GNUNET_CRYPTO_ecdsa_ecdh(&(priv->ecdsa_key), ecc, &hash) == 
GNUNET_SYSERR)
+         return -1;
+       break;
+  case GNUNET_IDENTITY_TYPE_EDDSA:
+       if (GNUNET_CRYPTO_eddsa_ecdh(&(priv->eddsa_key), ecc, &hash) == 
GNUNET_SYSERR)
+         return -1;
+       break;
+  default:
+       return -1;
+  }
+  struct GNUNET_CRYPTO_SymmetricSessionKey key;
+  struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
+  GNUNET_CRYPTO_hash_to_aes_key(&hash, &key, &iv);
+  GNUNET_CRYPTO_zero_keys(&hash, sizeof(hash));
+  const ssize_t decrypted = GNUNET_CRYPTO_symmetric_decrypt(block, size, &key, 
&iv, result);
+  GNUNET_CRYPTO_zero_keys(&key, sizeof(key));
+  GNUNET_CRYPTO_zero_keys(&iv, sizeof(iv));
+  return decrypted;
+}
+
+
 char *
 GNUNET_IDENTITY_public_key_to_string (const struct
                                       GNUNET_IDENTITY_PublicKey *key)
diff --git a/src/include/gnunet_identity_service.h 
b/src/include/gnunet_identity_service.h
index 17714fec4..8084a3a98 100644
--- a/src/include/gnunet_identity_service.h
+++ b/src/include/gnunet_identity_service.h
@@ -137,6 +137,33 @@ struct GNUNET_IDENTITY_PublicKey
 };
 
 
+/**
+ * An identity signature as per LSD0001.
+ */
+struct GNUNET_IDENTITY_Signature
+{
+  /**
+   * Type of signature.
+   * Defined by the GNS zone type value.
+   * In NBO.
+   */
+  uint32_t type;
+
+  union
+  {
+       /**
+        * An ECDSA signature
+        */
+    struct GNUNET_CRYPTO_EcdsaSignature ecdsa_signature;
+
+    /**
+     * AN EdDSA signature
+     */
+    struct GNUNET_CRYPTO_EddsaSignature eddsa_signature;
+  };
+};
+
+
 /**
  * Handle for an operation with the identity service.
  */
@@ -378,6 +405,194 @@ ssize_t
 GNUNET_IDENTITY_key_get_length (const struct GNUNET_IDENTITY_PublicKey *key);
 
 
+/**
+ * Get the compacted length of a #GNUNET_IDENTITY_Signature.
+ * Compacted means that it returns the minimum number of bytes this
+ * signature is long, as opposed to the union structure inside
+ * #GNUNET_IDENTITY_Signature.
+ * Useful for compact serializations.
+ *
+ * @param sig the signature.
+ * @return -1 on error, else the compacted length of the signature.
+ */
+ssize_t
+GNUNET_IDENTITY_signature_get_length (const struct GNUNET_IDENTITY_Signature 
*sig);
+
+
+/**
+ * Reads a #GNUNET_IDENTITY_PublicKey from a compact buffer.
+ * The buffer has to contain at least the compacted length of
+ * a #GNUNET_IDENTITY_PublicKey bytes.
+ * If the buffer is too small, the function returns -1 as error.
+ * If the buffer does not contain a valid key, it returns -2 as error.
+ *
+ * @param key the key
+ * @param buffer the buffer
+ * @param len the length of buffer
+ * @return -1 or -2 on error, else the amount of bytes read from the buffer
+ */
+ssize_t
+GNUNET_IDENTITY_read_key_from_buffer (struct GNUNET_IDENTITY_PublicKey *key,
+                                      const void* buffer,
+                                                                         
size_t len);
+
+
+/**
+ * Writes a #GNUNET_IDENTITY_PublicKey to a compact buffer.
+ * The buffer requires space for at least the compacted length of
+ * a #GNUNET_IDENTITY_PublicKey in bytes.
+ * If the buffer is too small, the function returns -1 as error.
+ * If the key is not valid, it returns -2 as error.
+ *
+ * @param key the key
+ * @param buffer the buffer
+ * @param len the length of buffer
+ * @return -1 or -2 on error, else the amount of bytes written to the buffer
+ */
+ssize_t
+GNUNET_IDENTITY_write_key_to_buffer (const struct GNUNET_IDENTITY_PublicKey 
*key,
+                                     void* buffer,
+                                                                        size_t 
len);
+
+
+/**
+ * @brief Sign a given block.
+ *
+ * The @a purpose data is the beginning of the data of which the signature is
+ * to be created. The `size` field in @a purpose must correctly indicate the
+ * number of bytes of the data structure, including its header. If possible,
+ * use #GNUNET_IDENTITY_private_key_sign() instead of this function.
+ *
+ * @param priv private key to use for the signing
+ * @param purpose what to sign (size, purpose)
+ * @param[out] sig where to write the signature
+ * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
+ */
+int
+GNUNET_IDENTITY_private_key_sign_ (const struct GNUNET_IDENTITY_PrivateKey 
*priv,
+                                          const struct 
GNUNET_CRYPTO_EccSignaturePurpose *purpose,
+                                                                  struct 
GNUNET_IDENTITY_Signature *sig);
+
+
+/**
+ * @brief Sign a given block with #GNUNET_IDENTITY_PrivateKey.
+ *
+ * The @a ps data must be a fixed-size struct for which the signature is to be
+ * created. The `size` field in @a ps->purpose must correctly indicate the
+ * number of bytes of the data structure, including its header.
+ *
+ * @param priv private key to use for the signing
+ * @param ps packed struct with what to sign, MUST begin with a purpose
+ * @param[out] sig where to write the signature
+ */
+#define GNUNET_IDENTITY_private_key_sign(priv,ps,sig) do {                \
+    /* check size is set correctly */                                     \
+    GNUNET_assert (htonl ((ps)->purpose.size) == sizeof (*(ps)));         \
+    /* check 'ps' begins with the purpose */                              \
+    GNUNET_static_assert (((void*) (ps)) ==                               \
+                          ((void*) &(ps)->purpose));                      \
+    GNUNET_assert (GNUNET_OK ==                                           \
+                      GNUNET_IDENTITY_private_key_sign_ (priv,               \
+                                              &(ps)->purpose,             \
+                                              sig));                      \
+} while (0)
+
+
+/**
+ * @brief Verify a given signature.
+ *
+ * The @a validate data is the beginning of the data of which the signature
+ * is to be verified. The `size` field in @a validate must correctly indicate
+ * the number of bytes of the data structure, including its header.  If @a
+ * purpose does not match the purpose given in @a validate (the latter must be
+ * in big endian), signature verification fails.  If possible,
+ * use #GNUNET_IDENTITY_public_key_verify() instead of this function (only if 
@a validate
+ * is not fixed-size, you must use this function directly).
+ *
+ * @param purpose what is the purpose that the signature should have?
+ * @param validate block to validate (size, purpose, data)
+ * @param sig signature that is being validated
+ * @param pub public key of the signer
+ * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
+ */
+int
+GNUNET_IDENTITY_public_key_verify_ (uint32_t purpose,
+                                           const struct 
GNUNET_CRYPTO_EccSignaturePurpose *validate,
+                                                                   const 
struct GNUNET_IDENTITY_Signature *sig,
+                                                                   const 
struct GNUNET_IDENTITY_PublicKey *pub);
+
+
+/**
+ * @brief Verify a given signature with #GNUNET_IDENTITY_PublicKey.
+ *
+ * The @a ps data must be a fixed-size struct for which the signature is to be
+ * created. The `size` field in @a ps->purpose must correctly indicate the
+ * number of bytes of the data structure, including its header.
+ *
+ * @param purp purpose of the signature, must match 'ps->purpose.purpose'
+ *              (except in host byte order)
+ * @param ps packed struct with what to sign, MUST begin with a purpose
+ * @param sig where to read the signature from
+ * @param pub public key to use for the verifying
+ */
+#define GNUNET_IDENTITY_public_key_verify(purp,ps,sig,pub) ({             \
+    /* check size is set correctly */                                     \
+    GNUNET_assert (ntohl ((ps)->purpose.size) == sizeof (*(ps)));         \
+    /* check 'ps' begins with the purpose */                              \
+    GNUNET_static_assert (((void*) (ps)) ==                               \
+                          ((void*) &(ps)->purpose));                      \
+       GNUNET_IDENTITY_public_key_verify_(purp,                              \
+                                       &(ps)->purpose,                    \
+                                       sig,                               \
+                                       pub);                              \
+  })
+
+
+/**
+ * Encrypt a block with #GNUNET_IDENTITY_PublicKey and derives a
+ * #GNUNET_CRYPTO_EcdhePublicKey which is required for decryption
+ * using ecdh to derive a symmetric key.
+ *
+ * @param block the block to encrypt
+ * @param size the size of the @a block
+ * @param pub public key to use for ecdh
+ * @param ecc where to write the ecc public key
+ * @param result the output parameter in which to store the encrypted result
+ *               can be the same or overlap with @c block
+ * @returns the size of the encrypted block, -1 for errors.
+ *          Due to the use of CFB and therefore an effective stream cipher,
+ *          this size should be the same as @c len.
+ */
+ssize_t
+GNUNET_IDENTITY_public_key_encrypt(const void *block,
+                                   size_t size,
+                                   const struct GNUNET_IDENTITY_PublicKey *pub,
+                                                                  struct 
GNUNET_CRYPTO_EcdhePublicKey *ecc,
+                                                                  void 
*result);
+
+
+/**
+ * Decrypt a given block with #GNUNET_IDENTITY_PrivateKey and a given
+ * #GNUNET_CRYPTO_EcdhePublicKey using ecdh to derive a symmetric key.
+ *
+ * @param block the data to decrypt, encoded as returned by encrypt
+ * @param size the size of the @a block to decrypt
+ * @param priv private key to use for ecdh
+ * @param ecc the ecc public key
+ * @param result address to store the result at
+ *               can be the same or overlap with @c block
+ * @return -1 on failure, size of decrypted block on success.
+ *         Due to the use of CFB and therefore an effective stream cipher,
+ *         this size should be the same as @c size.
+ */
+ssize_t
+GNUNET_IDENTITY_private_key_decrypt(const void *block,
+                                    size_t size,
+                                    const struct GNUNET_IDENTITY_PrivateKey 
*priv,
+                                                                       const 
struct GNUNET_CRYPTO_EcdhePublicKey *ecc,
+                                                                   void 
*result);
+
+
 /**
  * Creates a (Base32) string representation of the public key.
  * The resulting string encodes a compacted representation of the key.

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]