/* This file is part of GNUnet. Copyright (C) 2013 GNUnet e.V. GNUnet is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . SPDX-License-Identifier: AGPL3.0-or-later */ /** * @author Christian Grothoff * * @file * Identity service; implements identity management for GNUnet * * @defgroup identity Identity service * Identity management. * * Egos in GNUnet are ECDSA keys. You assume an ego by using (signing * with) a particular private key. As GNUnet users are expected to * have many egos, we need an identity service to allow users to * manage their egos. The identity service manages the egos (private * keys) of the local user; it does NOT manage egos of other users * (public keys). For giving names to other users and manage their * public keys securely, we use GNS. * * @see [Documentation](https://gnunet.org/identity-subsystem) * * @{ */ #ifndef GNUNET_IDENTITY_SERVICE_H #define GNUNET_IDENTITY_SERVICE_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_util_lib.h" /** * Version number of GNUnet Identity API. */ #define GNUNET_IDENTITY_VERSION 0x00000100 enum GNUNET_IDENTITY_KeyType { /** * The identity type. The value is the same as the * PKEY record type. */ GNUNET_IDENTITY_TYPE_ECDSA = 65536, /** * EDDSA identity. The value is the same as the EDKEY * record type. */ GNUNET_IDENTITY_TYPE_EDDSA = 65556 }; /** * Handle to access the identity service. */ struct GNUNET_IDENTITY_Handle; /** * Handle for a ego. */ struct GNUNET_IDENTITY_Ego; /** * A private key for an identity as per LSD0001. */ struct GNUNET_IDENTITY_PrivateKey { /** * Type of public key. * Defined by the GNS zone type value. * In NBO. */ uint32_t type; union { /** * An ECDSA identity key. */ struct GNUNET_CRYPTO_EcdsaPrivateKey ecdsa_key; /** * AN EdDSA identtiy key */ struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_key; }; }; /** * An identity key as per LSD0001. */ struct GNUNET_IDENTITY_PublicKey { /** * Type of public key. * Defined by the GNS zone type value. * In NBO. */ uint32_t type; union { /** * An ECDSA identity key. */ struct GNUNET_CRYPTO_EcdsaPublicKey ecdsa_key; /** * AN EdDSA identtiy key */ struct GNUNET_CRYPTO_EddsaPublicKey eddsa_key; }; }; /** * 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; /** * Obtain the ECC key associated with a ego. * * @param ego the ego * @return associated ECC key, valid as long as the ego is valid */ const struct GNUNET_IDENTITY_PrivateKey * GNUNET_IDENTITY_ego_get_private_key (const struct GNUNET_IDENTITY_Ego *ego); /** * Obtain the ego representing 'anonymous' users. * * @return handle for the anonymous user, MUST NOT be freed */ struct GNUNET_IDENTITY_Ego * GNUNET_IDENTITY_ego_get_anonymous (void); /** * Get the identifier (public key) of an ego. * * @param ego identity handle with the private key * @param pk set to ego's public key */ void GNUNET_IDENTITY_ego_get_public_key (struct GNUNET_IDENTITY_Ego *ego, struct GNUNET_IDENTITY_PublicKey *pk); /** * Method called to inform about the egos of this peer. * * When used with #GNUNET_IDENTITY_connect, this function is * initially called for all egos and then again whenever a * ego's name changes or if it is deleted. At the end of * the initial pass over all egos, the function is once called * with 'NULL' for @a ego. That does NOT mean that the callback won't * be invoked in the future or that there was an error. * * When used with #GNUNET_IDENTITY_create or #GNUNET_IDENTITY_get, * this function is only called ONCE, and 'NULL' being passed in * @a ego does indicate an error (i.e. name is taken or no default * value is known). If @a ego is non-NULL and if '*ctx' * is set in those callbacks, the value WILL be passed to a subsequent * call to the identity callback of #GNUNET_IDENTITY_connect (if * that one was not NULL). * * When an identity is renamed, this function is called with the * (known) @a ego but the NEW @a name. * * When an identity is deleted, this function is called with the * (known) ego and "NULL" for the @a name. In this case, * the @a ego is henceforth invalid (and the @a ctx should also be * cleaned up). * * @param cls closure * @param ego ego handle * @param ctx context for application to store data for this ego * (during the lifetime of this process, initially NULL) * @param name name assigned by the user for this ego, * NULL if the user just deleted the ego and it * must thus no longer be used */ typedef void (*GNUNET_IDENTITY_Callback) (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *name); /** * Connect to the identity service. * * @param cfg Configuration to contact the identity service. * @param cb function to call on all identity events, can be NULL * @param cb_cls closure for @a cb * @return handle to communicate with identity service */ struct GNUNET_IDENTITY_Handle * GNUNET_IDENTITY_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_IDENTITY_Callback cb, void *cb_cls); /** * Obtain the ego that is currently preferred/default for a service. * * @param id identity service to query * @param service_name for which service is an identity wanted * @param cb function to call with the result (will only be called once) * @param cb_cls closure for @a cb * @return handle to abort the operation */ struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_get (struct GNUNET_IDENTITY_Handle *id, const char *service_name, GNUNET_IDENTITY_Callback cb, void *cb_cls); /** * Function called once the requested operation has * been completed. * * @param cls closure * @param emsg NULL on success, otherwise an error message */ typedef void (*GNUNET_IDENTITY_Continuation) (void *cls, const char *emsg); /** * Set the preferred/default ego for a service. * * @param id identity service to inform * @param service_name for which service is an identity set * @param ego new default identity to be set for this service * @param cont function to call once the operation finished * @param cont_cls closure for @a cont * @return handle to abort the operation */ struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_set (struct GNUNET_IDENTITY_Handle *id, const char *service_name, struct GNUNET_IDENTITY_Ego *ego, GNUNET_IDENTITY_Continuation cont, void *cont_cls); /** * Disconnect from identity service. * * @param h identity service to disconnect */ void GNUNET_IDENTITY_disconnect (struct GNUNET_IDENTITY_Handle *h); /** * Function called once the requested operation has * been completed. * * @param cls closure * @param pk private key, NULL on error * @param emsg error message, NULL on success */ typedef void (*GNUNET_IDENTITY_CreateContinuation) ( void *cls, const struct GNUNET_IDENTITY_PrivateKey *pk, const char *emsg); /** * Create a new ego with the given name. * * @param id identity service to use * @param name desired name * @param privkey desired private key or NULL to create one * @param ktype the type of key to create. Ignored if privkey != NULL. * @param cont function to call with the result (will only be called once) * @param cont_cls closure for @a cont * @return handle to abort the operation */ struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_create (struct GNUNET_IDENTITY_Handle *id, const char *name, const struct GNUNET_IDENTITY_PrivateKey *privkey, enum GNUNET_IDENTITY_KeyType ktype, GNUNET_IDENTITY_CreateContinuation cont, void *cont_cls); /** * Renames an existing ego. * * @param id identity service to use * @param old_name old name * @param new_name desired new name * @param cb function to call with the result (will only be called once) * @param cb_cls closure for @a cb * @return handle to abort the operation */ struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_rename (struct GNUNET_IDENTITY_Handle *id, const char *old_name, const char *new_name, GNUNET_IDENTITY_Continuation cb, void *cb_cls); /** * Delete an existing ego. * * @param id identity service to use * @param name name of the identity to delete * @param cb function to call with the result (will only be called once) * @param cb_cls closure for @a cb * @return handle to abort the operation */ struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_delete (struct GNUNET_IDENTITY_Handle *id, const char *name, GNUNET_IDENTITY_Continuation cb, void *cb_cls); /** * Cancel an identity operation. Note that the operation MAY still * be executed; this merely cancels the continuation; if the request * was already transmitted, the service may still choose to complete * the operation. * * @param op operation to cancel */ void GNUNET_IDENTITY_cancel (struct GNUNET_IDENTITY_Operation *op); /** * Get the compacted length of a #GNUNET_IDENTITY_PublicKey. * Compacted means that it returns the minimum number of bytes this * key is long, as opposed to the union structure inside * #GNUNET_IDENTITY_PublicKey. * Useful for compact serializations. * * @param key the key. * @return -1 on error, else the compacted length of the key. */ ssize_t GNUNET_IDENTITY_key_get_length (const struct GNUNET_IDENTITY_PublicKey *key); /** * Reads a #GNUNET_IDENTITY_PublicKey from a compact buffer. * The buffer has to contain 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 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); /** * 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_Signature from a compact buffer. * The buffer has to contain at least the compacted length of * a #GNUNET_IDENTITY_Signature in 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 sig the signature * @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_signature_from_buffer (struct GNUNET_IDENTITY_Signature *sig, const void*buffer, size_t len); /** * Writes a #GNUNET_IDENTITY_Signature to a compact buffer. * The buffer requires space for at least the compacted length of * a #GNUNET_IDENTITY_Signature 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 sig the signature * @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_signature_to_buffer (const struct GNUNET_IDENTITY_Signature *sig, 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_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_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_sign(priv,ps,sig) do { \ /* 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_assert (GNUNET_OK == \ GNUNET_IDENTITY_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_signature_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_signature_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_signature_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_signature_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_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_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. * * @param key the key. * @return the string representation of the key, or NULL on error. */ char * GNUNET_IDENTITY_public_key_to_string (const struct GNUNET_IDENTITY_PublicKey *key); /** * Creates a (Base32) string representation of the private key. * The resulting string encodes a compacted representation of the key. * See also #GNUNET_IDENTITY_key_get_length. * * @param key the key. * @return the string representation of the key, or NULL on error. */ char * GNUNET_IDENTITY_private_key_to_string (const struct GNUNET_IDENTITY_PrivateKey *key); /** * Parses a (Base32) string representation of the public key. * See also #GNUNET_IDENTITY_public_key_to_string. * * @param str the encoded key. * @param key where to write the key. * @return GNUNET_SYSERR on error. */ enum GNUNET_GenericReturnValue GNUNET_IDENTITY_public_key_from_string (const char*str, struct GNUNET_IDENTITY_PublicKey *key); /** * Parses a (Base32) string representation of the private key. * See also #GNUNET_IDENTITY_private_key_to_string. * * @param str the encoded key. * @param key where to write the key. * @return GNUNET_SYSERR on error. */ enum GNUNET_GenericReturnValue GNUNET_IDENTITY_private_key_from_string (const char*str, struct GNUNET_IDENTITY_PrivateKey *key); /** * Retrieves the public key representation of a private key. * * @param privkey the private key. * @param key the public key result. * @return GNUNET_SYSERR on error. */ enum GNUNET_GenericReturnValue GNUNET_IDENTITY_key_get_public (const struct GNUNET_IDENTITY_PrivateKey *privkey, struct GNUNET_IDENTITY_PublicKey *key); /* ************* convenience API to lookup an ego ***************** */ /** * Function called with the result. * * @param cls closure * @param ego NULL on error / ego not found */ typedef void (*GNUNET_IDENTITY_EgoCallback) (void *cls, struct GNUNET_IDENTITY_Ego *ego); /** * Handle for ego lookup. */ struct GNUNET_IDENTITY_EgoLookup; /** * Lookup an ego by name. * * @param cfg configuration to use * @param name name to look up * @param cb callback to invoke with the result * @param cb_cls closure for @a cb * @return NULL on error */ struct GNUNET_IDENTITY_EgoLookup * GNUNET_IDENTITY_ego_lookup (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *name, GNUNET_IDENTITY_EgoCallback cb, void *cb_cls); /** * Abort ego lookup attempt. * * @param el handle for lookup to abort */ void GNUNET_IDENTITY_ego_lookup_cancel (struct GNUNET_IDENTITY_EgoLookup *el); /** * Function called with the result. * * @param cls closure * @param ego NULL on error / ego not found * @param ego_name NULL on error, name of the ego otherwise */ typedef void (*GNUNET_IDENTITY_EgoSuffixCallback) ( void *cls, const struct GNUNET_IDENTITY_PrivateKey *priv, const char *ego_name); /** * Handle for suffix lookup. */ struct GNUNET_IDENTITY_EgoSuffixLookup; /** * Obtain the ego with the maximum suffix match between the * ego's name and the given domain name @a suffix. I.e., given * a @a suffix "a.b.c" and egos with names "d.a.b.c", "b.c" and "c", * we return the ego for "b.c". * * @param cfg configuration to use * @param suffix for which domain name suffix is an identity wanted * @param cb function to call with the result (will only be called once) * @param cb_cls closure for @a cb * @return handle to abort the operation */ struct GNUNET_IDENTITY_EgoSuffixLookup * GNUNET_IDENTITY_ego_lookup_by_suffix (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *suffix, GNUNET_IDENTITY_EgoSuffixCallback cb, void *cb_cls); /** * Abort ego suffix lookup attempt. * * @param el handle for lookup to abort */ void GNUNET_IDENTITY_ego_lookup_by_suffix_cancel ( struct GNUNET_IDENTITY_EgoSuffixLookup *el); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_IDENTITY_SERVICE_H */ #endif /** @} */ /* end of group identity */ /* end of gnunet_identity_service.h */