summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTheJackiMonster <thejackimonster@gmail.com>2020-11-05 21:20:38 +0100
committerTheJackiMonster <thejackimonster@gmail.com>2020-11-05 21:20:38 +0100
commitc07ae5c8d29202466f066e4dcddbfd091513db7c (patch)
treec99961354915549f33643414720a5432b25b4847 /src
parent77842546903ef7296c863987f9a60e5f0ead14d1 (diff)
additional abstraction for identity keys
Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/conversation/conversation.h2
-rw-r--r--src/conversation/gnunet-service-conversation.c8
-rw-r--r--src/gnsrecord/gnsrecord_misc.c11
-rw-r--r--src/identity/identity_api.c164
-rw-r--r--src/include/gnunet_identity_service.h215
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
@@ -138,6 +138,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.
*/
struct GNUNET_IDENTITY_Operation;
@@ -379,6 +406,194 @@ 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.
* See also #GNUNET_IDENTITY_key_get_length.