X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Finclude%2Fgnunet_crypto_lib.h;h=07cade0e30dc49016850d902fe3fda5b350764d4;hb=abdec5e11ff11bb10d32c013e11344a54786f80f;hp=9da6488f26bb314dac9fd9ee8b201f7a6080ca71;hpb=d1bbc74bc202a18f898aa98524517a7c0791e682;p=oweals%2Fgnunet.git diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h index 9da6488f2..07cade0e3 100644 --- a/src/include/gnunet_crypto_lib.h +++ b/src/include/gnunet_crypto_lib.h @@ -1,10 +1,10 @@ /* This file is part of GNUnet. - (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2012 Christian Grothoff (and other contributing authors) + Copyright (C) 2001-2013 GNUnet e.V. GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2, or (at your + by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but @@ -14,8 +14,8 @@ You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ /** @@ -27,6 +27,17 @@ * @author Gerd Knorr * @author Ioana Patrascu * @author Tzvetan Horozov + * @author Jeffrey Burdges + * + * @defgroup crypto Crypto library: cryptographic operations + * Provides cryptographic primitives. + * + * @see [Documentation](https://gnunet.org/crypto-api) + * + * @defgroup hash Crypto library: hash operations + * Provides hashing and operations on hashes. + * + * @see [Documentation](https://gnunet.org/crypto-api) */ #ifndef GNUNET_CRYPTO_LIB_H @@ -40,27 +51,64 @@ extern "C" #endif #endif +/** + * @brief A 512-bit hashcode. These are the default length for GNUnet, using SHA-512. + */ +struct GNUNET_HashCode +{ + uint32_t bits[512 / 8 / sizeof (uint32_t)]; /* = 16 */ +}; + + + +/** + * @brief A 256-bit hashcode. Used under special conditions, like when space + * is critical and security is not impacted by it. + */ +struct GNUNET_ShortHashCode +{ + uint32_t bits[256 / 8 / sizeof (uint32_t)]; /* = 8 */ +}; + + +/** + * The identity of the host (wraps the signing key of the peer). + */ +struct GNUNET_PeerIdentity; + #include "gnunet_common.h" -#include "gnunet_scheduler_lib.h" +#include + + +/** + * Maximum length of an ECC signature. + * Note: round up to multiple of 8 minus 2 for alignment. + */ +#define GNUNET_CRYPTO_ECC_SIGNATURE_DATA_ENCODING_LENGTH 126 + /** - * Desired quality level for cryptographic operations. + * Desired quality level for random numbers. + * @ingroup crypto */ enum GNUNET_CRYPTO_Quality { /** * No good quality of the operation is needed (i.e., * random numbers can be pseudo-random). + * @ingroup crypto */ GNUNET_CRYPTO_QUALITY_WEAK, /** * High-quality operations are desired. + * @ingroup crypto */ GNUNET_CRYPTO_QUALITY_STRONG, /** * Randomness for IVs etc. is required. + * @ingroup crypto */ GNUNET_CRYPTO_QUALITY_NONCE }; @@ -71,77 +119,16 @@ enum GNUNET_CRYPTO_Quality */ #define GNUNET_CRYPTO_AES_KEY_LENGTH (256/8) -/** - * @brief Length of RSA encrypted data (2048 bit) - * - * We currently do not handle encryption of data - * that can not be done in a single call to the - * RSA methods (read: large chunks of data). - * We should never need that, as we can use - * the GNUNET_CRYPTO_hash for larger pieces of data for signing, - * and for encryption, we only need to encode sessionkeys! - */ -#define GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH 256 - -/** - * Length of an RSA KEY (n,e,len), 2048 bit (=256 octests) key n, 2 byte e - */ -#define GNUNET_CRYPTO_RSA_KEY_LENGTH 258 - /** * Length of a hash value */ #define GNUNET_CRYPTO_HASH_LENGTH (512/8) /** - * Maximum length of an ECC signature. - * Note: round up to multiple of 8 minus 2 for alignment. - */ -#define GNUNET_CRYPTO_ECC_SIGNATURE_DATA_ENCODING_LENGTH 126 - -/** - * Maximum length of the public key (q-point, Q = dP) when encoded. - */ -#define GNUNET_CRYPTO_ECC_MAX_PUBLIC_KEY_LENGTH 76 - - -/** - * The private information of an RSA key pair. - */ -struct GNUNET_CRYPTO_RsaPrivateKey; - -/** - * The private information of an ECC private key. - */ -struct GNUNET_CRYPTO_EccPrivateKey; - - -GNUNET_NETWORK_STRUCT_BEGIN - -/** - * GNUnet mandates a certain format for the encoding - * of private RSA key information that is provided - * by the RSA implementations. This format is used - * to serialize a private RSA key (typically when - * writing it to disk). + * How many characters (without 0-terminator) are our ASCII-encoded + * public keys (ECDSA/EDDSA/ECDHE). */ -struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded -{ - /** - * Total size of the structure, in bytes, in big-endian! - */ - uint16_t len GNUNET_PACKED; - uint16_t sizen GNUNET_PACKED; /* in big-endian! */ - uint16_t sizee GNUNET_PACKED; /* in big-endian! */ - uint16_t sized GNUNET_PACKED; /* in big-endian! */ - uint16_t sizep GNUNET_PACKED; /* in big-endian! */ - uint16_t sizeq GNUNET_PACKED; /* in big-endian! */ - uint16_t sizedmp1 GNUNET_PACKED; /* in big-endian! */ - uint16_t sizedmq1 GNUNET_PACKED; /* in big-endian! */ - /* followed by the actual values */ -}; -GNUNET_NETWORK_STRUCT_END - +#define GNUNET_CRYPTO_PKEY_ASCII_LENGTH 52 /** * @brief 0-terminated ASCII encoding of a struct GNUNET_HashCode. @@ -152,33 +139,15 @@ struct GNUNET_CRYPTO_HashAsciiEncoded }; -/** - * @brief 0-terminated ASCII encoding of a 'struct GNUNET_ShortHashCode'. - */ -struct GNUNET_CRYPTO_ShortHashAsciiEncoded -{ - unsigned char short_encoding[53]; -}; - - - -/** - * @brief an RSA signature - */ -struct GNUNET_CRYPTO_RsaSignature -{ - unsigned char sig[GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH]; -}; - - GNUNET_NETWORK_STRUCT_BEGIN + /** - * @brief header of what an RSA signature signs + * @brief header of what an ECC signature signs * this must be followed by "size - 8" bytes of * the actual signed data */ -struct GNUNET_CRYPTO_RsaSignaturePurpose +struct GNUNET_CRYPTO_EccSignaturePurpose { /** * How many bytes does this signature sign? @@ -199,119 +168,135 @@ struct GNUNET_CRYPTO_RsaSignaturePurpose /** - * @brief A public key. + * @brief an ECC signature using EdDSA. + * See https://gnunet.org/ed25519 */ -struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded +struct GNUNET_CRYPTO_EddsaSignature { + /** - * In big-endian, must be GNUNET_CRYPTO_RSA_KEY_LENGTH+4 + * R value. */ - uint16_t len GNUNET_PACKED; + unsigned char r[256 / 8]; /** - * Size of n in key; in big-endian! + * S value. */ - uint16_t sizen GNUNET_PACKED; + unsigned char s[256 / 8]; + +}; + + + +/** + * @brief an ECC signature using ECDSA + */ +struct GNUNET_CRYPTO_EcdsaSignature +{ /** - * The key itself, contains n followed by e. + * R value. */ - unsigned char key[GNUNET_CRYPTO_RSA_KEY_LENGTH]; + unsigned char r[256 / 8]; /** - * Padding (must be 0) + * S value. */ - uint16_t padding GNUNET_PACKED; + unsigned char s[256 / 8]; + }; /** - * RSA Encrypted data. + * Public ECC key (always for Curve25519) encoded in a format suitable + * for network transmission and EdDSA signatures. */ -struct GNUNET_CRYPTO_RsaEncryptedData +struct GNUNET_CRYPTO_EddsaPublicKey { - unsigned char encoding[GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH]; + /** + * Q consists of an x- and a y-value, each mod p (256 bits), given + * here in affine coordinates and Ed25519 standard compact format. + */ + unsigned char q_y[256 / 8]; + }; /** - * @brief header of what an ECC signature signs - * this must be followed by "size - 8" bytes of - * the actual signed data + * Public ECC key (always for Curve25519) encoded in a format suitable + * for network transmission and ECDSA signatures. */ -struct GNUNET_CRYPTO_EccSignaturePurpose +struct GNUNET_CRYPTO_EcdsaPublicKey { /** - * How many bytes does this signature sign? - * (including this purpose header); in network - * byte order (!). - */ - uint32_t size GNUNET_PACKED; - - /** - * What does this signature vouch for? This - * must contain a GNUNET_SIGNATURE_PURPOSE_XXX - * constant (from gnunet_signatures.h). In - * network byte order! + * Q consists of an x- and a y-value, each mod p (256 bits), given + * here in affine coordinates and Ed25519 standard compact format. */ - uint32_t purpose GNUNET_PACKED; + unsigned char q_y[256 / 8]; }; /** - * @brief an ECC signature + * The identity of the host (wraps the signing key of the peer). */ -struct GNUNET_CRYPTO_EccSignature +struct GNUNET_PeerIdentity { - /** - * Overall size of the signature data. - */ - uint16_t size GNUNET_PACKED; + struct GNUNET_CRYPTO_EddsaPublicKey public_key; +}; + +/** + * Public ECC key (always for Curve25519) encoded in a format suitable + * for network transmission and encryption (ECDH), + * See http://cr.yp.to/ecdh.html + */ +struct GNUNET_CRYPTO_EcdhePublicKey +{ /** - * S-expression, padded with zeros. + * Q consists of an x- and a y-value, each mod p (256 bits), given + * here in affine coordinates and Ed25519 standard compact format. */ - char sexpr[GNUNET_CRYPTO_ECC_SIGNATURE_DATA_ENCODING_LENGTH]; + unsigned char q_y[256 / 8]; }; /** - * Public ECC key (always for NIST P-521) encoded in a format suitable - * for network transmission as created using 'gcry_sexp_sprint'. + * Private ECC key encoded for transmission. To be used only for ECDH + * key exchange (ECDHE to be precise). */ -struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded +struct GNUNET_CRYPTO_EcdhePrivateKey { /** - * Size of the encoding, in network byte order. + * d is a value mod n, where n has at most 256 bits. */ - uint16_t size GNUNET_PACKED; + unsigned char d[256 / 8]; - /** - * Actual length of the q-point binary encoding. - */ - uint16_t len GNUNET_PACKED; +}; +/** + * Private ECC key encoded for transmission. To be used only for ECDSA + * signatures. + */ +struct GNUNET_CRYPTO_EcdsaPrivateKey +{ /** - * 0-padded q-point in binary encoding (GCRYPT_MPI_FMT_USG). + * d is a value mod n, where n has at most 256 bits. */ - unsigned char key[GNUNET_CRYPTO_ECC_MAX_PUBLIC_KEY_LENGTH]; -}; + unsigned char d[256 / 8]; +}; /** - * Private ECC key encoded for transmission (with length prefix). + * Private ECC key encoded for transmission. To be used only for EdDSA + * signatures. */ -struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded +struct GNUNET_CRYPTO_EddsaPrivateKey { /** - * Overall size of the private key in network byte order. + * d is a value mod n, where n has at most 256 bits. */ - uint16_t size; - - /* followd by S-expression, opaque to applications */ - - /* FIXME: consider defining padding to make this a fixed-size struct */ + unsigned char d[256 / 8]; }; @@ -319,25 +304,33 @@ struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded /** * @brief type for session keys */ -struct GNUNET_CRYPTO_AesSessionKey +struct GNUNET_CRYPTO_SymmetricSessionKey { /** - * Actual key. + * Actual key for AES. + */ + unsigned char aes_key[GNUNET_CRYPTO_AES_KEY_LENGTH]; + + /** + * Actual key for TwoFish. */ - unsigned char key[GNUNET_CRYPTO_AES_KEY_LENGTH]; + unsigned char twofish_key[GNUNET_CRYPTO_AES_KEY_LENGTH]; }; + GNUNET_NETWORK_STRUCT_END /** * @brief IV for sym cipher * * NOTE: must be smaller (!) in size than the - * struct GNUNET_HashCode. + * `struct GNUNET_HashCode`. */ -struct GNUNET_CRYPTO_AesInitializationVector +struct GNUNET_CRYPTO_SymmetricInitializationVector { - unsigned char iv[GNUNET_CRYPTO_AES_KEY_LENGTH / 2]; + unsigned char aes_iv[GNUNET_CRYPTO_AES_KEY_LENGTH / 2]; + + unsigned char twofish_iv[GNUNET_CRYPTO_AES_KEY_LENGTH / 2]; }; @@ -350,10 +343,64 @@ struct GNUNET_CRYPTO_AuthKey }; +/** + * Size of paillier plain texts and public keys. + * Private keys and ciphertexts are twice this size. + */ +#define GNUNET_CRYPTO_PAILLIER_BITS 2048 + + +/** + * Paillier public key. + */ +struct GNUNET_CRYPTO_PaillierPublicKey +{ + /** + * N value. + */ + unsigned char n[GNUNET_CRYPTO_PAILLIER_BITS / 8]; +}; + + +/** + * Paillier public key. + */ +struct GNUNET_CRYPTO_PaillierPrivateKey +{ + /** + * Lambda-component of the private key. + */ + unsigned char lambda[GNUNET_CRYPTO_PAILLIER_BITS / 8]; + /** + * Mu-component of the private key. + */ + unsigned char mu[GNUNET_CRYPTO_PAILLIER_BITS / 8]; +}; + + +/** + * Paillier ciphertext. + */ +struct GNUNET_CRYPTO_PaillierCiphertext +{ + /** + * Guaranteed minimum number of homomorphic operations with this ciphertext, + * in network byte order (NBO). + */ + int32_t remaining_ops GNUNET_PACKED; + + /** + * The bits of the ciphertext. + */ + unsigned char bits[GNUNET_CRYPTO_PAILLIER_BITS * 2 / 8]; +}; + + /* **************** Functions and Macros ************* */ /** - * Seed a weak random generator. Only GNUNET_CRYPTO_QUALITY_WEAK-mode generator + * @ingroup crypto + * Seed a weak random generator. Only #GNUNET_CRYPTO_QUALITY_WEAK-mode generator * can be seeded. * * @param seed the seed to use @@ -362,16 +409,31 @@ void GNUNET_CRYPTO_seed_weak_random (int32_t seed); +/** + * @ingroup hash + * Calculate the checksum of a buffer in one step. + * + * @param buf buffer to calculate CRC over + * @param len number of bytes in @a buf + * @return crc8 value + */ +uint8_t +GNUNET_CRYPTO_crc8_n (const void *buf, + size_t len); + + /** * Perform an incremental step in a CRC16 (for TCP/IP) calculation. * * @param sum current sum, initially 0 * @param buf buffer to calculate CRC over (must be 16-bit aligned) - * @param len number of bytes in hdr, must be multiple of 2 - * @return updated crc sum (must be subjected to GNUNET_CRYPTO_crc16_finish to get actual crc16) + * @param len number of bytes in @a buf, must be multiple of 2 + * @return updated crc sum (must be subjected to #GNUNET_CRYPTO_crc16_finish to get actual crc16) */ uint32_t -GNUNET_CRYPTO_crc16_step (uint32_t sum, const void *buf, size_t len); +GNUNET_CRYPTO_crc16_step (uint32_t sum, + const void *buf, + size_t len); /** @@ -385,90 +447,119 @@ GNUNET_CRYPTO_crc16_finish (uint32_t sum); /** + * @ingroup hash * Calculate the checksum of a buffer in one step. * - * @param buf buffer to calculate CRC over (must be 16-bit aligned) - * @param len number of bytes in hdr, must be multiple of 2 + * @param buf buffer to calculate CRC over (must be 16-bit aligned) + * @param len number of bytes in @a buf, must be multiple of 2 * @return crc16 value */ uint16_t -GNUNET_CRYPTO_crc16_n (const void *buf, size_t len); +GNUNET_CRYPTO_crc16_n (const void *buf, + size_t len); + + /** + * @ingroup hash * Compute the CRC32 checksum for the first len * bytes of the buffer. * * @param buf the data over which we're taking the CRC - * @param len the length of the buffer in bytes + * @param len the length of the buffer @a buf in bytes * @return the resulting CRC32 checksum */ int32_t -GNUNET_CRYPTO_crc32_n (const void *buf, size_t len); +GNUNET_CRYPTO_crc32_n (const void *buf, + size_t len); /** + * @ingroup crypto + * Fill block with a random values. + * + * @param mode desired quality of the random number + * @param buffer the buffer to fill + * @param length buffer length + */ +void +GNUNET_CRYPTO_random_block (enum GNUNET_CRYPTO_Quality mode, + void *buffer, + size_t length); + +/** + * @ingroup crypto * Produce a random value. * * @param mode desired quality of the random number * @param i the upper limit (exclusive) for the random number - * @return a random value in the interval [0,i) (exclusive). + * @return a random value in the interval [0,@a i) (exclusive). */ uint32_t -GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode, uint32_t i); +GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode, + uint32_t i); /** + * @ingroup crypto * Random on unsigned 64-bit values. * * @param mode desired quality of the random number - * @param max value returned will be in range [0,max) (exclusive) + * @param max value returned will be in range [0,@a max) (exclusive) * @return random 64-bit number */ uint64_t -GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, uint64_t max); +GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, + uint64_t max); /** + * @ingroup crypto * Get an array with a random permutation of the * numbers 0...n-1. - * @param mode GNUNET_CRYPTO_QUALITY_STRONG if the strong (but expensive) PRNG should be used, GNUNET_CRYPTO_QUALITY_WEAK otherwise + * @param mode #GNUNET_CRYPTO_QUALITY_STRONG if the strong (but expensive) PRNG should be used, + * #GNUNET_CRYPTO_QUALITY_WEAK or #GNUNET_CRYPTO_QUALITY_NONCE otherwise * @param n the size of the array * @return the permutation array (allocated from heap) */ unsigned int * -GNUNET_CRYPTO_random_permute (enum GNUNET_CRYPTO_Quality mode, unsigned int n); +GNUNET_CRYPTO_random_permute (enum GNUNET_CRYPTO_Quality mode, + unsigned int n); /** - * Create a new Session key. + * @ingroup crypto + * Create a new random session key. * * @param key key to initialize */ void -GNUNET_CRYPTO_aes_create_session_key (struct GNUNET_CRYPTO_AesSessionKey *key); +GNUNET_CRYPTO_symmetric_create_session_key (struct GNUNET_CRYPTO_SymmetricSessionKey *key); /** - * Encrypt a block with the public key of another - * host that uses the same cyper. + * @ingroup crypto + * Encrypt a block using a symmetric sessionkey. * * @param block the block to encrypt - * @param len the size of the block + * @param size the size of the @a block * @param sessionkey the key used to encrypt * @param iv the initialization vector to use, use INITVALUE * for streams. * @return the size of the encrypted block, -1 for errors */ ssize_t -GNUNET_CRYPTO_aes_encrypt (const void *block, size_t len, - const struct GNUNET_CRYPTO_AesSessionKey *sessionkey, - const struct GNUNET_CRYPTO_AesInitializationVector - *iv, void *result); +GNUNET_CRYPTO_symmetric_encrypt (const void *block, + size_t size, + const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey, + const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, + void *result); /** - * Decrypt a given block with the sessionkey. + * @ingroup crypto + * Decrypt a given block using a symmetric sessionkey. * * @param block the data to decrypt, encoded as returned by encrypt * @param size how big is the block? @@ -478,24 +569,27 @@ GNUNET_CRYPTO_aes_encrypt (const void *block, size_t len, * @return -1 on failure, size of decrypted block on success */ ssize_t -GNUNET_CRYPTO_aes_decrypt (const void *block, size_t size, - const struct GNUNET_CRYPTO_AesSessionKey *sessionkey, - const struct GNUNET_CRYPTO_AesInitializationVector - *iv, void *result); +GNUNET_CRYPTO_symmetric_decrypt (const void *block, + size_t size, + const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey, + const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, + void *result); /** + * @ingroup crypto * @brief Derive an IV * @param iv initialization vector * @param skey session key * @param salt salt for the derivation - * @param salt_len size of the salt + * @param salt_len size of the @a salt * @param ... pairs of void * & size_t for context chunks, terminated by NULL */ void -GNUNET_CRYPTO_aes_derive_iv (struct GNUNET_CRYPTO_AesInitializationVector *iv, - const struct GNUNET_CRYPTO_AesSessionKey *skey, - const void *salt, size_t salt_len, ...); +GNUNET_CRYPTO_symmetric_derive_iv (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, + const struct GNUNET_CRYPTO_SymmetricSessionKey *skey, + const void *salt, + size_t salt_len, ...); /** @@ -503,173 +597,149 @@ GNUNET_CRYPTO_aes_derive_iv (struct GNUNET_CRYPTO_AesInitializationVector *iv, * @param iv initialization vector * @param skey session key * @param salt salt for the derivation - * @param salt_len size of the salt + * @param salt_len size of the @a salt * @param argp pairs of void * & size_t for context chunks, terminated by NULL */ void -GNUNET_CRYPTO_aes_derive_iv_v (struct GNUNET_CRYPTO_AesInitializationVector *iv, - const struct GNUNET_CRYPTO_AesSessionKey *skey, - const void *salt, size_t salt_len, va_list argp); +GNUNET_CRYPTO_symmetric_derive_iv_v (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, + const struct GNUNET_CRYPTO_SymmetricSessionKey *skey, + const void *salt, + size_t salt_len, + va_list argp); /** + * @ingroup hash * Convert hash to ASCII encoding. * @param block the hash code * @param result where to store the encoding (struct GNUNET_CRYPTO_HashAsciiEncoded can be * safely cast to char*, a '\\0' termination is set). */ void -GNUNET_CRYPTO_hash_to_enc (const struct GNUNET_HashCode * block, +GNUNET_CRYPTO_hash_to_enc (const struct GNUNET_HashCode *block, struct GNUNET_CRYPTO_HashAsciiEncoded *result); /** - * Convert short hash to ASCII encoding. - * - * @param block the hash code - * @param result where to store the encoding (struct GNUNET_CRYPTO_ShortHashAsciiEncoded can be - * safely cast to char*, a '\\0' termination is set). - */ -void -GNUNET_CRYPTO_short_hash_to_enc (const struct GNUNET_CRYPTO_ShortHashCode * block, - struct GNUNET_CRYPTO_ShortHashAsciiEncoded *result); - - -/** + * @ingroup hash * Convert ASCII encoding back to a 'struct GNUNET_HashCode' * * @param enc the encoding - * @param enclen number of characters in 'enc' (without 0-terminator, which can be missing) - * @param result where to store the GNUNET_CRYPTO_hash code - * @return GNUNET_OK on success, GNUNET_SYSERR if result has the wrong encoding - */ -int -GNUNET_CRYPTO_hash_from_string2 (const char *enc, size_t enclen, - struct GNUNET_HashCode * result); - - -/** - * Convert ASCII encoding back to a 'struct GNUNET_CRYPTO_ShortHash' - * - * @param enc the encoding - * @param enclen number of characters in 'enc' (without 0-terminator, which can be missing) - * @param result where to store the GNUNET_CRYPTO_hash code - * @return GNUNET_OK on success, GNUNET_SYSERR if result has the wrong encoding + * @param enclen number of characters in @a enc (without 0-terminator, which can be missing) + * @param result where to store the hash code + * @return #GNUNET_OK on success, #GNUNET_SYSERR if result has the wrong encoding */ int -GNUNET_CRYPTO_short_hash_from_string2 (const char *enc, size_t enclen, - struct GNUNET_CRYPTO_ShortHashCode * result); +GNUNET_CRYPTO_hash_from_string2 (const char *enc, + size_t enclen, + struct GNUNET_HashCode *result); /** - * Convert ASCII encoding back to struct GNUNET_HashCode + * @ingroup hash + * Convert ASCII encoding back to `struct GNUNET_HashCode` * * @param enc the encoding * @param result where to store the hash code - * @return GNUNET_OK on success, GNUNET_SYSERR if result has the wrong encoding + * @return #GNUNET_OK on success, #GNUNET_SYSERR if result has the wrong encoding */ #define GNUNET_CRYPTO_hash_from_string(enc, result) \ GNUNET_CRYPTO_hash_from_string2 (enc, strlen(enc), result) /** - * Convert ASCII encoding back to a 'struct GNUNET_CRYPTO_ShortHash' - * - * @param enc the encoding - * @param result where to store the GNUNET_CRYPTO_ShortHash - * @return GNUNET_OK on success, GNUNET_SYSERR if result has the wrong encoding - */ -#define GNUNET_CRYPTO_short_hash_from_string(enc, result) \ - GNUNET_CRYPTO_short_hash_from_string2 (enc, strlen(enc), result) - - -/** - * Compare function for ShortHashCodes, producing a total ordering - * of all hashcodes. + * @ingroup hash * - * @param h1 some hash code - * @param h2 some hash code - * @return 1 if h1 > h2, -1 if h1 < h2 and 0 if h1 == h2. - */ -int -GNUNET_CRYPTO_short_hash_cmp (const struct GNUNET_CRYPTO_ShortHashCode * h1, - const struct GNUNET_CRYPTO_ShortHashCode * h2); - -/** - * Compute the distance between 2 hashcodes. - * The computation must be fast, not involve - * a.a or a.e (they're used elsewhere), and - * be somewhat consistent. And of course, the - * result should be a positive number. + * Compute the distance between 2 hashcodes. The + * computation must be fast, not involve @a a[0] or @a a[4] (they're used + * elsewhere), and be somewhat consistent. And of course, the result + * should be a positive number. * * @param a some hash code * @param b some hash code * @return number between 0 and UINT32_MAX */ uint32_t -GNUNET_CRYPTO_hash_distance_u32 (const struct GNUNET_HashCode * a, - const struct GNUNET_HashCode * b); +GNUNET_CRYPTO_hash_distance_u32 (const struct GNUNET_HashCode *a, + const struct GNUNET_HashCode *b); /** + * @ingroup hash * Compute hash of a given block. * * @param block the data to hash - * @param size size of the block + * @param size size of the @a block * @param ret pointer to where to write the hashcode */ void -GNUNET_CRYPTO_hash (const void *block, size_t size, struct GNUNET_HashCode * ret); +GNUNET_CRYPTO_hash (const void *block, + size_t size, + struct GNUNET_HashCode *ret); + + +/** + * Context for cummulative hashing. + */ +struct GNUNET_HashContext; /** - * Compute short (256-bit) hash of a given block. + * Start incremental hashing operation. * - * @param block the data to hash - * @param size size of the block - * @param ret pointer to where to write the hashcode + * @return context for incremental hash computation + */ +struct GNUNET_HashContext * +GNUNET_CRYPTO_hash_context_start (void); + + +/** + * Add data to be hashed. + * + * @param hc cummulative hash context + * @param buf data to add + * @param size number of bytes in @a buf */ void -GNUNET_CRYPTO_short_hash (const void *block, size_t size, - struct GNUNET_CRYPTO_ShortHashCode * ret); +GNUNET_CRYPTO_hash_context_read (struct GNUNET_HashContext *hc, + const void *buf, + size_t size); /** - * Double short (256-bit) hash to create a long hash. + * Finish the hash computation. * - * @param sh short hash to double - * @param dh where to store the (doubled) long hash (not really a hash) + * @param hc hash context to use, is freed in the process + * @param r_hash where to write the latest / final hash code */ void -GNUNET_CRYPTO_short_hash_double (const struct GNUNET_CRYPTO_ShortHashCode *sh, - struct GNUNET_HashCode *dh); +GNUNET_CRYPTO_hash_context_finish (struct GNUNET_HashContext *hc, + struct GNUNET_HashCode *r_hash); /** - * Truncate doubled short hash back to a short hash. + * Abort hashing, do not bother calculating final result. * - * @param dh doubled short hash to reduce again - * @param sh where to store the short hash - * @return GNUNET_OK on success, GNUNET_SYSERR if this was not a - * doubled short hash + * @param hc hash context to destroy */ -int -GNUNET_CRYPTO_short_hash_from_truncation (const struct GNUNET_HashCode *dh, - struct GNUNET_CRYPTO_ShortHashCode *sh); +void +GNUNET_CRYPTO_hash_context_abort (struct GNUNET_HashContext *hc); /** + * @ingroup hash * Calculate HMAC of a message (RFC 2104) * * @param key secret key * @param plaintext input plaintext - * @param plaintext_len length of plaintext + * @param plaintext_len length of @a plaintext * @param hmac where to store the hmac */ void GNUNET_CRYPTO_hmac (const struct GNUNET_CRYPTO_AuthKey *key, - const void *plaintext, size_t plaintext_len, - struct GNUNET_HashCode * hmac); + const void *plaintext, + size_t plaintext_len, + struct GNUNET_HashCode *hmac); /** @@ -679,9 +749,9 @@ GNUNET_CRYPTO_hmac (const struct GNUNET_CRYPTO_AuthKey *key, * @param cls closure * @param res resulting hash, NULL on error */ -typedef void (*GNUNET_CRYPTO_HashCompletedCallback) (void *cls, - const struct GNUNET_HashCode * - res); +typedef void +(*GNUNET_CRYPTO_HashCompletedCallback) (void *cls, + const struct GNUNET_HashCode *res); /** @@ -689,19 +759,22 @@ typedef void (*GNUNET_CRYPTO_HashCompletedCallback) (void *cls, */ struct GNUNET_CRYPTO_FileHashContext; + /** + * @ingroup hash * Compute the hash of an entire file. * * @param priority scheduling priority to use * @param filename name of file to hash * @param blocksize number of bytes to process in one task * @param callback function to call upon completion - * @param callback_cls closure for callback + * @param callback_cls closure for @a callback * @return NULL on (immediate) errror */ struct GNUNET_CRYPTO_FileHashContext * GNUNET_CRYPTO_hash_file (enum GNUNET_SCHEDULER_Priority priority, - const char *filename, size_t blocksize, + const char *filename, + size_t blocksize, GNUNET_CRYPTO_HashCompletedCallback callback, void *callback_cls); @@ -716,6 +789,7 @@ GNUNET_CRYPTO_hash_file_cancel (struct GNUNET_CRYPTO_FileHashContext *fhc); /** + * @ingroup hash * Create a random hash code. * * @param mode desired quality level @@ -723,48 +797,53 @@ GNUNET_CRYPTO_hash_file_cancel (struct GNUNET_CRYPTO_FileHashContext *fhc); */ void GNUNET_CRYPTO_hash_create_random (enum GNUNET_CRYPTO_Quality mode, - struct GNUNET_HashCode * result); + struct GNUNET_HashCode *result); /** - * compute result(delta) = b - a + * @ingroup hash + * compute @a result = @a b - @a a * * @param a some hash code * @param b some hash code - * @param result set to b - a + * @param result set to @a b - @a a */ void -GNUNET_CRYPTO_hash_difference (const struct GNUNET_HashCode * a, - const struct GNUNET_HashCode * b, - struct GNUNET_HashCode * result); +GNUNET_CRYPTO_hash_difference (const struct GNUNET_HashCode *a, + const struct GNUNET_HashCode *b, + struct GNUNET_HashCode *result); /** - * compute result(b) = a + delta + * @ingroup hash + * compute @a result = @a a + @a delta * * @param a some hash code * @param delta some hash code - * @param result set to a + delta + * @param result set to @a a + @a delta */ void -GNUNET_CRYPTO_hash_sum (const struct GNUNET_HashCode * a, - const struct GNUNET_HashCode * delta, - struct GNUNET_HashCode * result); +GNUNET_CRYPTO_hash_sum (const struct GNUNET_HashCode *a, + const struct GNUNET_HashCode *delta, + struct GNUNET_HashCode *result); /** + * @ingroup hash * compute result = a ^ b * * @param a some hash code * @param b some hash code - * @param result set to a ^ b + * @param result set to @a a ^ @a b */ void -GNUNET_CRYPTO_hash_xor (const struct GNUNET_HashCode * a, const struct GNUNET_HashCode * b, - struct GNUNET_HashCode * result); +GNUNET_CRYPTO_hash_xor (const struct GNUNET_HashCode *a, + const struct GNUNET_HashCode *b, + struct GNUNET_HashCode *result); /** + * @ingroup hash * Convert a hashcode into a key. * * @param hc hash code that serves to generate the key @@ -773,66 +852,72 @@ GNUNET_CRYPTO_hash_xor (const struct GNUNET_HashCode * a, const struct GNUNET_Ha */ void GNUNET_CRYPTO_hash_to_aes_key (const struct GNUNET_HashCode * hc, - struct GNUNET_CRYPTO_AesSessionKey *skey, - struct GNUNET_CRYPTO_AesInitializationVector - *iv); + struct GNUNET_CRYPTO_SymmetricSessionKey *skey, + struct GNUNET_CRYPTO_SymmetricInitializationVector *iv); /** + * @ingroup hash * Obtain a bit from a hashcode. * - * @param code the GNUNET_CRYPTO_hash to index bit-wise + * @param code the `struct GNUNET_HashCode` to index bit-wise * @param bit index into the hashcode, [0...159] * @return Bit \a bit from hashcode \a code, -1 for invalid index */ int -GNUNET_CRYPTO_hash_get_bit (const struct GNUNET_HashCode * code, unsigned int bit); +GNUNET_CRYPTO_hash_get_bit (const struct GNUNET_HashCode *code, + unsigned int bit); + /** + * @ingroup hash * Determine how many low order bits match in two - * struct GNUNET_HashCodes. i.e. - 010011 and 011111 share + * `struct GNUNET_HashCodes`. i.e. - 010011 and 011111 share * the first two lowest order bits, and therefore the * return value is two (NOT XOR distance, nor how many * bits match absolutely!). * * @param first the first hashcode * @param second the hashcode to compare first to - * * @return the number of bits that match */ unsigned int -GNUNET_CRYPTO_hash_matching_bits (const struct GNUNET_HashCode * first, - const struct GNUNET_HashCode * second); +GNUNET_CRYPTO_hash_matching_bits (const struct GNUNET_HashCode *first, + const struct GNUNET_HashCode *second); /** + * @ingroup hash * Compare function for HashCodes, producing a total ordering * of all hashcodes. * * @param h1 some hash code * @param h2 some hash code - * @return 1 if h1 > h2, -1 if h1 < h2 and 0 if h1 == h2. + * @return 1 if @a h1 > @a h2, -1 if @a h1 < @a h2 and 0 if @a h1 == @a h2. */ int -GNUNET_CRYPTO_hash_cmp (const struct GNUNET_HashCode * h1, const struct GNUNET_HashCode * h2); +GNUNET_CRYPTO_hash_cmp (const struct GNUNET_HashCode *h1, + const struct GNUNET_HashCode *h2); /** + * @ingroup hash * Find out which of the two GNUNET_CRYPTO_hash codes is closer to target * in the XOR metric (Kademlia). * * @param h1 some hash code * @param h2 some hash code * @param target some hash code - * @return -1 if h1 is closer, 1 if h2 is closer and 0 if h1==h2. + * @return -1 if @a h1 is closer, 1 if @a h2 is closer and 0 if @a h1== @a h2. */ int -GNUNET_CRYPTO_hash_xorcmp (const struct GNUNET_HashCode * h1, - const struct GNUNET_HashCode * h2, - const struct GNUNET_HashCode * target); +GNUNET_CRYPTO_hash_xorcmp (const struct GNUNET_HashCode *h1, + const struct GNUNET_HashCode *h2, + const struct GNUNET_HashCode *target); /** + * @ingroup hash * @brief Derive an authentication key * @param key authentication key * @param rkey root key @@ -842,12 +927,13 @@ GNUNET_CRYPTO_hash_xorcmp (const struct GNUNET_HashCode * h1, */ void GNUNET_CRYPTO_hmac_derive_key_v (struct GNUNET_CRYPTO_AuthKey *key, - const struct GNUNET_CRYPTO_AesSessionKey *rkey, + const struct GNUNET_CRYPTO_SymmetricSessionKey *rkey, const void *salt, size_t salt_len, va_list argp); /** + * @ingroup hash * @brief Derive an authentication key * @param key authentication key * @param rkey root key @@ -857,45 +943,61 @@ GNUNET_CRYPTO_hmac_derive_key_v (struct GNUNET_CRYPTO_AuthKey *key, */ void GNUNET_CRYPTO_hmac_derive_key (struct GNUNET_CRYPTO_AuthKey *key, - const struct GNUNET_CRYPTO_AesSessionKey *rkey, - const void *salt, size_t salt_len, ...); + const struct GNUNET_CRYPTO_SymmetricSessionKey *rkey, + const void *salt, size_t salt_len, + ...); + /** + * @ingroup hash * @brief Derive key * @param result buffer for the derived key, allocated by caller * @param out_len desired length of the derived key * @param xtr_algo hash algorithm for the extraction phase, GCRY_MD_... * @param prf_algo hash algorithm for the expansion phase, GCRY_MD_... * @param xts salt - * @param xts_len length of xts + * @param xts_len length of @a xts * @param skm source key material - * @param skm_len length of skm + * @param skm_len length of @a skm * @param ... pair of void * & size_t for context chunks, terminated by NULL - * @return GNUNET_YES on success + * @return #GNUNET_YES on success */ int -GNUNET_CRYPTO_hkdf (void *result, size_t out_len, int xtr_algo, int prf_algo, - const void *xts, size_t xts_len, const void *skm, - size_t skm_len, ...); +GNUNET_CRYPTO_hkdf (void *result, + size_t out_len, + int xtr_algo, + int prf_algo, + const void *xts, + size_t xts_len, + const void *skm, + size_t skm_len, + ...); /** + * @ingroup hash * @brief Derive key * @param result buffer for the derived key, allocated by caller * @param out_len desired length of the derived key * @param xtr_algo hash algorithm for the extraction phase, GCRY_MD_... * @param prf_algo hash algorithm for the expansion phase, GCRY_MD_... * @param xts salt - * @param xts_len length of xts + * @param xts_len length of @a xts * @param skm source key material - * @param skm_len length of skm + * @param skm_len length of @a skm * @param argp va_list of void * & size_t pairs for context chunks - * @return GNUNET_YES on success + * @return #GNUNET_YES on success */ int -GNUNET_CRYPTO_hkdf_v (void *result, size_t out_len, int xtr_algo, int prf_algo, - const void *xts, size_t xts_len, const void *skm, - size_t skm_len, va_list argp); +GNUNET_CRYPTO_hkdf_v (void *result, + size_t out_len, + int xtr_algo, + int prf_algo, + const void *xts, + size_t xts_len, + const void *skm, + size_t skm_len, + va_list argp); /** @@ -903,470 +1005,1124 @@ GNUNET_CRYPTO_hkdf_v (void *result, size_t out_len, int xtr_algo, int prf_algo, * @param result buffer for the derived key, allocated by caller * @param out_len desired length of the derived key * @param xts salt - * @param xts_len length of xts + * @param xts_len length of @a xts * @param skm source key material - * @param skm_len length of skm + * @param skm_len length of @a skm * @param argp va_list of void * & size_t pairs for context chunks - * @return GNUNET_YES on success + * @return #GNUNET_YES on success */ int -GNUNET_CRYPTO_kdf_v (void *result, size_t out_len, const void *xts, - size_t xts_len, const void *skm, size_t skm_len, +GNUNET_CRYPTO_kdf_v (void *result, + size_t out_len, + const void *xts, + size_t xts_len, + const void *skm, + size_t skm_len, va_list argp); /** + * Deterministically generate a pseudo-random number uniformly from the + * integers modulo a libgcrypt mpi. + * + * @param[out] r MPI value set to the FDH + * @param n MPI to work modulo + * @param xts salt + * @param xts_len length of @a xts + * @param skm source key material + * @param skm_len length of @a skm + * @param ctx context string + */ +void +GNUNET_CRYPTO_kdf_mod_mpi (gcry_mpi_t *r, + gcry_mpi_t n, + const void *xts, size_t xts_len, + const void *skm, size_t skm_len, + const char *ctx); + + +/** + * @ingroup hash * @brief Derive key * @param result buffer for the derived key, allocated by caller * @param out_len desired length of the derived key * @param xts salt - * @param xts_len length of xts + * @param xts_len length of @a xts * @param skm source key material - * @param skm_len length of skm + * @param skm_len length of @a skm * @param ... void * & size_t pairs for context chunks - * @return GNUNET_YES on success + * @return #GNUNET_YES on success */ int -GNUNET_CRYPTO_kdf (void *result, size_t out_len, const void *xts, - size_t xts_len, const void *skm, size_t skm_len, ...); +GNUNET_CRYPTO_kdf (void *result, + size_t out_len, + const void *xts, + size_t xts_len, + const void *skm, + size_t skm_len, + ...); /** - * Convert a public key to a string. + * @ingroup crypto + * Extract the public key for the given private key. * - * @param pub key to convert - * @return string representing 'pub' + * @param priv the private key + * @param pub where to write the public key */ -char * -GNUNET_CRYPTO_rsa_public_key_to_string (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pub); - +void +GNUNET_CRYPTO_ecdsa_key_get_public (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, + struct GNUNET_CRYPTO_EcdsaPublicKey *pub); /** - * Convert a string representing a public key to a public key. + * @ingroup crypto + * Extract the public key for the given private key. * - * @param enc encoded public key - * @param enclen number of bytes in enc (without 0-terminator) - * @param pub where to store the public key - * @return GNUNET_OK on success + * @param priv the private key + * @param pub where to write the public key */ -int -GNUNET_CRYPTO_rsa_public_key_from_string (const char *enc, - size_t enclen, - struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pub); - +void +GNUNET_CRYPTO_eddsa_key_get_public (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, + struct GNUNET_CRYPTO_EddsaPublicKey *pub); -/** - * Encode the private key in a format suitable for - * storing it into a file. - * @return encoding of the private key - */ -struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded * -GNUNET_CRYPTO_rsa_encode_key (const struct GNUNET_CRYPTO_RsaPrivateKey *hostkey); /** - * Decode the private key from the data-format back - * to the "normal", internal format. + * @ingroup crypto + * Extract the public key for the given private key. * - * @param buf the buffer where the private key data is stored - * @param len the length of the data in 'buffer' - * @return NULL on error + * @param priv the private key + * @param pub where to write the public key */ -struct GNUNET_CRYPTO_RsaPrivateKey * -GNUNET_CRYPTO_rsa_decode_key (const char *buf, uint16_t len); +void +GNUNET_CRYPTO_ecdhe_key_get_public (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv, + struct GNUNET_CRYPTO_EcdhePublicKey *pub); + + +/** + * Convert a public key to a string. + * + * @param pub key to convert + * @return string representing @a pub + */ +char * +GNUNET_CRYPTO_ecdsa_public_key_to_string (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub); + + +/** + * Convert a public key to a string. + * + * @param pub key to convert + * @return string representing @a pub + */ +char * +GNUNET_CRYPTO_eddsa_public_key_to_string (const struct GNUNET_CRYPTO_EddsaPublicKey *pub); + + +/** + * Convert a string representing a public key to a public key. + * + * @param enc encoded public key + * @param enclen number of bytes in @a enc (without 0-terminator) + * @param pub where to store the public key + * @return #GNUNET_OK on success + */ +int +GNUNET_CRYPTO_ecdsa_public_key_from_string (const char *enc, + size_t enclen, + struct GNUNET_CRYPTO_EcdsaPublicKey *pub); + + +/** + * Convert a string representing a private key to a private key. + * + * @param enc encoded public key + * @param enclen number of bytes in @a enc (without 0-terminator) + * @param priv where to store the private key + * @return #GNUNET_OK on success + */ +int +GNUNET_CRYPTO_eddsa_private_key_from_string (const char *enc, + size_t enclen, + struct GNUNET_CRYPTO_EddsaPrivateKey *pub); + + +/** + * Convert a string representing a public key to a public key. + * + * @param enc encoded public key + * @param enclen number of bytes in @a enc (without 0-terminator) + * @param pub where to store the public key + * @return #GNUNET_OK on success + */ +int +GNUNET_CRYPTO_eddsa_public_key_from_string (const char *enc, + size_t enclen, + struct GNUNET_CRYPTO_EddsaPublicKey *pub); + + +/** + * @ingroup crypto + * Create a new private key by reading it from a file. If the + * files does not exist, create a new key and write it to the + * file. Caller must free return value. Note that this function + * can not guarantee that another process might not be trying + * the same operation on the same file at the same time. + * If the contents of the file + * are invalid the old file is deleted and a fresh key is + * created. + * + * @param filename name of file to use to store the key + * @return new private key, NULL on error (for example, + * permission denied); free using #GNUNET_free + */ +struct GNUNET_CRYPTO_EcdsaPrivateKey * +GNUNET_CRYPTO_ecdsa_key_create_from_file (const char *filename); /** + * @ingroup crypto * Create a new private key by reading it from a file. If the * files does not exist, create a new key and write it to the - * file. Caller must free return value. Note that this function + * file. Caller must free return value. Note that this function * can not guarantee that another process might not be trying * the same operation on the same file at the same time. * If the contents of the file * are invalid the old file is deleted and a fresh key is * created. * - * @param filename name of file to use for storage + * @param filename name of file to use to store the key * @return new private key, NULL on error (for example, - * permission denied) - * @deprecated use 'GNUNET_CRYPTO_rsa_key_create_start' instead + * permission denied); free using #GNUNET_free */ -struct GNUNET_CRYPTO_RsaPrivateKey * -GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename); +struct GNUNET_CRYPTO_EddsaPrivateKey * +GNUNET_CRYPTO_eddsa_key_create_from_file (const char *filename); + + +/** + * Forward declaration to simplify #include-structure. + */ +struct GNUNET_CONFIGURATION_Handle; /** - * Open existing private key file and read it. If the - * file does not exist, or the contents of the file are - * invalid, the function fails - * Caller must free returned value. + * @ingroup crypto + * Create a new private key by reading our peer's key from + * the file specified in the configuration. * - * @return a private key, NULL on error (for example, - * permission denied) or when file does not exist or contains invalid - * data. + * @param cfg the configuration to use + * @return new private key, NULL on error (for example, + * permission denied); free using #GNUNET_free */ -struct GNUNET_CRYPTO_RsaPrivateKey * -GNUNET_CRYPTO_rsa_key_create_from_existing_file (const char *filename); +struct GNUNET_CRYPTO_EddsaPrivateKey * +GNUNET_CRYPTO_eddsa_key_create_from_configuration (const struct GNUNET_CONFIGURATION_Handle *cfg); /** - * Handle to cancel private key generation. + * @ingroup crypto + * Create a new private key. Caller must free return value. + * + * @return fresh private key; free using #GNUNET_free */ -struct GNUNET_CRYPTO_RsaKeyGenerationContext; +struct GNUNET_CRYPTO_EcdsaPrivateKey * +GNUNET_CRYPTO_ecdsa_key_create (void); /** - * Function called upon completion of 'GNUNET_CRYPTO_rsa_key_create_async'. + * @ingroup crypto + * Create a new private key. Caller must free return value. * - * @param cls closure - * @param pk NULL on error, otherwise the private key (which must be free'd by the callee) - * @param emsg NULL on success, otherwise an error message + * @return fresh private key; free using #GNUNET_free */ -typedef void (*GNUNET_CRYPTO_RsaKeyCallback)(void *cls, - struct GNUNET_CRYPTO_RsaPrivateKey *pk, - const char *emsg); +struct GNUNET_CRYPTO_EddsaPrivateKey * +GNUNET_CRYPTO_eddsa_key_create (void); /** - * Create a new private key by reading it from a file. If the files - * does not exist, create a new key and write it to the file. If the - * contents of the file are invalid the old file is deleted and a - * fresh key is created. + * @ingroup crypto + * Create a new private key. Clear with #GNUNET_CRYPTO_ecdhe_key_clear(). * - * @param filename name of file to use for storage - * @param cont function to call when done (or on errors) - * @param cont_cls closure for 'cont' - * @return handle to abort operation, NULL on fatal errors (cont will not be called if NULL is returned) + * @param[out] pk set to fresh private key; + * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ -struct GNUNET_CRYPTO_RsaKeyGenerationContext * -GNUNET_CRYPTO_rsa_key_create_start (const char *filename, - GNUNET_CRYPTO_RsaKeyCallback cont, - void *cont_cls); +int +GNUNET_CRYPTO_ecdhe_key_create2 (struct GNUNET_CRYPTO_EcdhePrivateKey *pk); /** - * Abort RSA key generation. + * @ingroup crypto + * Create a new private key. Caller must free return value. * - * @param gc key generation context to abort + * @return fresh private key; free using #GNUNET_free + */ +struct GNUNET_CRYPTO_EcdhePrivateKey * +GNUNET_CRYPTO_ecdhe_key_create (void); + + +/** + * @ingroup crypto + * Clear memory that was used to store a private key. + * + * @param pk location of the key */ void -GNUNET_CRYPTO_rsa_key_create_stop (struct GNUNET_CRYPTO_RsaKeyGenerationContext *gc); +GNUNET_CRYPTO_eddsa_key_clear (struct GNUNET_CRYPTO_EddsaPrivateKey *pk); /** + * @ingroup crypto + * Clear memory that was used to store a private key. + * + * @param pk location of the key + */ +void +GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk); + + +/** + * @ingroup crypto + * Clear memory that was used to store a private key. + * + * @param pk location of the key + */ +void +GNUNET_CRYPTO_ecdhe_key_clear (struct GNUNET_CRYPTO_EcdhePrivateKey *pk); + + +/** + * @ingroup crypto + * Get the shared private key we use for anonymous users. + * + * @return "anonymous" private key; do not free + */ +const struct GNUNET_CRYPTO_EcdsaPrivateKey * +GNUNET_CRYPTO_ecdsa_key_get_anonymous (void); + + +/** + * @ingroup crypto * Setup a hostkey file for a peer given the name of the * configuration file (!). This function is used so that * at a later point code can be certain that reading a * hostkey is fast (for example in time-dependent testcases). - * +* * @param cfg_name name of the configuration file to use */ void -GNUNET_CRYPTO_rsa_setup_hostkey (const char *cfg_name); +GNUNET_CRYPTO_eddsa_setup_hostkey (const char *cfg_name); /** - * Deterministically (!) create a private key using only the - * given HashCode as input to the PRNG. + * @ingroup crypto + * Retrieve the identity of the host's peer. * - * @param hc "random" input to PRNG - * @return some private key purely dependent on input + * @param cfg configuration to use + * @param dst pointer to where to write the peer identity + * @return #GNUNET_OK on success, #GNUNET_SYSERR if the identity + * could not be retrieved */ -struct GNUNET_CRYPTO_RsaPrivateKey * -GNUNET_CRYPTO_rsa_key_create_from_hash (const struct GNUNET_HashCode *hc); +int +GNUNET_CRYPTO_get_peer_identity (const struct GNUNET_CONFIGURATION_Handle *cfg, + struct GNUNET_PeerIdentity *dst); /** - * Free memory occupied by the private key. + * Compare two Peer Identities. * - * @param key pointer to the memory to free + * @param first first peer identity + * @param second second peer identity + * @return bigger than 0 if first > second, + * 0 if they are the same + * smaller than 0 if second > first + */ +int +GNUNET_CRYPTO_cmp_peer_identity (const struct GNUNET_PeerIdentity *first, + const struct GNUNET_PeerIdentity *second); + + +/** + * Internal structure used to cache pre-calculated values for DLOG calculation. + */ +struct GNUNET_CRYPTO_EccDlogContext; + + +/** + * Point on a curve (always for Curve25519) encoded in a format suitable + * for network transmission (ECDH), see http://cr.yp.to/ecdh.html. + */ +struct GNUNET_CRYPTO_EccPoint +{ + /** + * Q consists of an x- and a y-value, each mod p (256 bits), given + * here in affine coordinates and Ed25519 standard compact format. + */ + unsigned char q_y[256 / 8]; +}; + + +/** + * Do pre-calculation for ECC discrete logarithm for small factors. + * + * @param max maximum value the factor can be + * @param mem memory to use (should be smaller than @a max), must not be zero. + * @return NULL on error + */ +struct GNUNET_CRYPTO_EccDlogContext * +GNUNET_CRYPTO_ecc_dlog_prepare (unsigned int max, + unsigned int mem); + + +/** + * Calculate ECC discrete logarithm for small factors. + * Opposite of #GNUNET_CRYPTO_ecc_dexp(). + * + * @param dlc precalculated values, determine range of factors + * @param input point on the curve to factor + * @return INT_MAX if dlog failed, otherwise the factor + */ +int +GNUNET_CRYPTO_ecc_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc, + gcry_mpi_point_t input); + + +/** + * Multiply the generator g of the elliptic curve by @a val + * to obtain the point on the curve representing @a val. + * Afterwards, point addition will correspond to integer + * addition. #GNUNET_CRYPTO_ecc_dlog() can be used to + * convert a point back to an integer (as long as the + * integer is smaller than the MAX of the @a edc context). + * + * @param edc calculation context for ECC operations + * @param val value to encode into a point + * @return representation of the value as an ECC point, + * must be freed using #GNUNET_CRYPTO_ecc_free() + */ +gcry_mpi_point_t +GNUNET_CRYPTO_ecc_dexp (struct GNUNET_CRYPTO_EccDlogContext *edc, + int val); + + +/** + * Multiply the generator g of the elliptic curve by @a val + * to obtain the point on the curve representing @a val. + * + * @param edc calculation context for ECC operations + * @param val (positive) value to encode into a point + * @return representation of the value as an ECC point, + * must be freed using #GNUNET_CRYPTO_ecc_free() + */ +gcry_mpi_point_t +GNUNET_CRYPTO_ecc_dexp_mpi (struct GNUNET_CRYPTO_EccDlogContext *edc, + gcry_mpi_t val); + + +/** + * Multiply the point @a p on the elliptic curve by @a val. + * + * @param edc calculation context for ECC operations + * @param p point to multiply + * @param val (positive) value to encode into a point + * @return representation of the value as an ECC point, + * must be freed using #GNUNET_CRYPTO_ecc_free() + */ +gcry_mpi_point_t +GNUNET_CRYPTO_ecc_pmul_mpi (struct GNUNET_CRYPTO_EccDlogContext *edc, + gcry_mpi_point_t p, + gcry_mpi_t val); + + +/** + * Convert point value to binary representation. + * + * @param edc calculation context for ECC operations + * @param point computational point representation + * @param[out] bin binary point representation */ void -GNUNET_CRYPTO_rsa_key_free (struct GNUNET_CRYPTO_RsaPrivateKey *key); +GNUNET_CRYPTO_ecc_point_to_bin (struct GNUNET_CRYPTO_EccDlogContext *edc, + gcry_mpi_point_t point, + struct GNUNET_CRYPTO_EccPoint *bin); /** - * Extract the public key of the host. + * Convert binary representation of a point to computational representation. * - * @param priv the private key - * @param pub where to write the public key + * @param edc calculation context for ECC operations + * @param bin binary point representation + * @return computational representation + */ +gcry_mpi_point_t +GNUNET_CRYPTO_ecc_bin_to_point (struct GNUNET_CRYPTO_EccDlogContext *edc, + const struct GNUNET_CRYPTO_EccPoint *bin); + + +/** + * Add two points on the elliptic curve. + * + * @param edc calculation context for ECC operations + * @param a some value + * @param b some value + * @return @a a + @a b, must be freed using #GNUNET_CRYPTO_ecc_free() + */ +gcry_mpi_point_t +GNUNET_CRYPTO_ecc_add (struct GNUNET_CRYPTO_EccDlogContext *edc, + gcry_mpi_point_t a, + gcry_mpi_point_t b); + + +/** + * Obtain a random point on the curve and its + * additive inverse. Both returned values + * must be freed using #GNUNET_CRYPTO_ecc_free(). + * + * @param edc calculation context for ECC operations + * @param[out] r set to a random point on the curve + * @param[out] r_inv set to the additive inverse of @a r */ void -GNUNET_CRYPTO_rsa_key_get_public (const struct GNUNET_CRYPTO_RsaPrivateKey - *priv, - struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded - *pub); +GNUNET_CRYPTO_ecc_rnd (struct GNUNET_CRYPTO_EccDlogContext *edc, + gcry_mpi_point_t *r, + gcry_mpi_point_t *r_inv); /** - * Get hash of the public key that corresponds to a private key. + * Obtain a random scalar for point multiplication on the curve and + * its multiplicative inverse. * - * @param key RSA private key - * @param id buffer for hash of the public key + * @param edc calculation context for ECC operations + * @param[out] r set to a random scalar on the curve + * @param[out] r_inv set to the multiplicative inverse of @a r */ void -GNUNET_CRYPTO_rsa_get_public_key_hash (struct GNUNET_CRYPTO_RsaPrivateKey *key, - struct GNUNET_HashCode *id); +GNUNET_CRYPTO_ecc_rnd_mpi (struct GNUNET_CRYPTO_EccDlogContext *edc, + gcry_mpi_t *r, + gcry_mpi_t *r_inv); /** - * Encrypt a block with the public key of another host that uses the - * same cyper. + * Generate a random value mod n. * - * @param block the block to encrypt - * @param size the size of block - * @param publicKey the encoded public key used to encrypt - * @param target where to store the encrypted block - * @return GNUNET_SYSERR on error, GNUNET_OK if ok + * @param edc ECC context + * @return random value mod n. + */ +gcry_mpi_t +GNUNET_CRYPTO_ecc_random_mod_n (struct GNUNET_CRYPTO_EccDlogContext *edc); + + +/** + * Free a point value returned by the API. + * + * @param p point to free + */ +void +GNUNET_CRYPTO_ecc_free (gcry_mpi_point_t p); + + +/** + * Release precalculated values. + * + * @param dlc dlog context + */ +void +GNUNET_CRYPTO_ecc_dlog_release (struct GNUNET_CRYPTO_EccDlogContext *dlc); + + +/** + * @ingroup crypto + * Derive key material from a public and a private ECC key. + * + * @param priv private key to use for the ECDH (x) + * @param pub public key to use for the ECDH (yG) + * @param key_material where to write the key material (xyG) + * @return #GNUNET_SYSERR on error, #GNUNET_OK on success */ int -GNUNET_CRYPTO_rsa_encrypt (const void *block, size_t size, - const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded - *publicKey, - struct GNUNET_CRYPTO_RsaEncryptedData *target); +GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv, + const struct GNUNET_CRYPTO_EcdhePublicKey *pub, + struct GNUNET_HashCode *key_material); /** - * Decrypt a given block with the hostkey. + * @ingroup crypto + * Derive key material from a ECDH public key and a private EdDSA key. + * Dual to #GNUNET_CRRYPTO_ecdh_eddsa. * - * @param key the key to use - * @param block the data to decrypt, encoded as returned by encrypt, not consumed - * @param result pointer to a location where the result can be stored - * @param max how many bytes of a result are expected? Must be exact. - * @return the size of the decrypted block (that is, size) or -1 on error + * @param priv private key from EdDSA to use for the ECDH (x) + * @param pub public key to use for the ECDH (yG) + * @param key_material where to write the key material H(h(x)yG) + * @return #GNUNET_SYSERR on error, #GNUNET_OK on success */ -ssize_t -GNUNET_CRYPTO_rsa_decrypt (const struct GNUNET_CRYPTO_RsaPrivateKey *key, - const struct GNUNET_CRYPTO_RsaEncryptedData *block, - void *result, size_t max); +int +GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, + const struct GNUNET_CRYPTO_EcdhePublicKey *pub, + struct GNUNET_HashCode *key_material); + +/** + * @ingroup crypto + * Derive key material from a ECDH public key and a private ECDSA key. + * Dual to #GNUNET_CRRYPTO_ecdh_ecdsa. + * + * @param priv private key from ECDSA to use for the ECDH (x) + * @param pub public key to use for the ECDH (yG) + * @param key_material where to write the key material H(h(x)yG) + * @return #GNUNET_SYSERR on error, #GNUNET_OK on success + */ +int +GNUNET_CRYPTO_ecdsa_ecdh (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, + const struct GNUNET_CRYPTO_EcdhePublicKey *pub, + struct GNUNET_HashCode *key_material); /** - * Sign a given block. + * @ingroup crypto + * Derive key material from a EdDSA public key and a private ECDH key. + * Dual to #GNUNET_CRRYPTO_eddsa_ecdh. * - * @param key private key to use for the signing + * @param priv private key to use for the ECDH (y) + * @param pub public key from EdDSA to use for the ECDH (X=h(x)G) + * @param key_material where to write the key material H(yX)=H(h(x)yG) + * @return #GNUNET_SYSERR on error, #GNUNET_OK on success + */ +int +GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv, + const struct GNUNET_CRYPTO_EddsaPublicKey *pub, + struct GNUNET_HashCode *key_material); + +/** + * @ingroup crypto + * Derive key material from a EcDSA public key and a private ECDH key. + * Dual to #GNUNET_CRRYPTO_ecdsa_ecdh. + * + * @param priv private key to use for the ECDH (y) + * @param pub public key from ECDSA to use for the ECDH (X=h(x)G) + * @param key_material where to write the key material H(yX)=H(h(x)yG) + * @return #GNUNET_SYSERR on error, #GNUNET_OK on success + */ +int +GNUNET_CRYPTO_ecdh_ecdsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv, + const struct GNUNET_CRYPTO_EcdsaPublicKey *pub, + struct GNUNET_HashCode *key_material); + + +/** + * @ingroup crypto + * EdDSA sign a given block. + * + * @param priv private key to use for the signing * @param purpose what to sign (size, purpose) * @param sig where to write the signature - * @return GNUNET_SYSERR on error, GNUNET_OK on success + * @return #GNUNET_SYSERR on error, #GNUNET_OK on success */ int -GNUNET_CRYPTO_rsa_sign (const struct GNUNET_CRYPTO_RsaPrivateKey *key, - const struct GNUNET_CRYPTO_RsaSignaturePurpose *purpose, - struct GNUNET_CRYPTO_RsaSignature *sig); +GNUNET_CRYPTO_eddsa_sign (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, + const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, + struct GNUNET_CRYPTO_EddsaSignature *sig); /** - * Verify signature. Note that the caller MUST have already - * checked that "validate->size" bytes are actually available. + * @ingroup crypto + * ECDSA Sign a given block. * - * @param purpose what is the purpose that validate should have? + * @param priv private key to use for the signing + * @param purpose what to sign (size, purpose) + * @param sig where to write the signature + * @return #GNUNET_SYSERR on error, #GNUNET_OK on success + */ +int +GNUNET_CRYPTO_ecdsa_sign (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, + const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, + struct GNUNET_CRYPTO_EcdsaSignature *sig); + +/** + * @ingroup crypto + * Verify EdDSA signature. + * + * @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 publicKey public key of the signer - * @return GNUNET_OK if ok, GNUNET_SYSERR if invalid + * @param pub public key of the signer + * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid */ int -GNUNET_CRYPTO_rsa_verify (uint32_t purpose, - const struct GNUNET_CRYPTO_RsaSignaturePurpose - *validate, - const struct GNUNET_CRYPTO_RsaSignature *sig, - const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded - *publicKey); +GNUNET_CRYPTO_eddsa_verify (uint32_t purpose, + const struct GNUNET_CRYPTO_EccSignaturePurpose *validate, + const struct GNUNET_CRYPTO_EddsaSignature *sig, + const struct GNUNET_CRYPTO_EddsaPublicKey *pub); /** - * Function called upon completion of 'GNUNET_CRYPTO_ecc_key_create_async'. + * @ingroup crypto + * Verify ECDSA signature. * - * @param cls closure - * @param pk NULL on error, otherwise the private key (which must be free'd by the callee) - * @param emsg NULL on success, otherwise an error message + * @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 */ -typedef void (*GNUNET_CRYPTO_EccKeyCallback)(void *cls, - struct GNUNET_CRYPTO_EccPrivateKey *pk, - const char *emsg); +int +GNUNET_CRYPTO_ecdsa_verify (uint32_t purpose, + const struct GNUNET_CRYPTO_EccSignaturePurpose *validate, + const struct GNUNET_CRYPTO_EcdsaSignature *sig, + const struct GNUNET_CRYPTO_EcdsaPublicKey *pub); /** - * Free memory occupied by ECC key + * @ingroup crypto + * Derive a private key from a given private key and a label. + * Essentially calculates a private key 'h = H(l,P) * d mod n' + * where n is the size of the ECC group and P is the public + * key associated with the private key 'd'. * - * @param privatekey pointer to the memory to free + * @param priv original private key + * @param label label to use for key deriviation + * @param context additional context to use for HKDF of 'h'; + * typically the name of the subsystem/application + * @return derived private key + */ +struct GNUNET_CRYPTO_EcdsaPrivateKey * +GNUNET_CRYPTO_ecdsa_private_key_derive (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, + const char *label, + const char *context); + + +/** + * @ingroup crypto + * Derive a public key from a given public key and a label. + * Essentially calculates a public key 'V = H(l,P) * P'. + * + * @param pub original public key + * @param label label to use for key deriviation + * @param context additional context to use for HKDF of 'h'. + * typically the name of the subsystem/application + * @param result where to write the derived public key */ void -GNUNET_CRYPTO_ecc_key_free (struct GNUNET_CRYPTO_EccPrivateKey *privatekey); +GNUNET_CRYPTO_ecdsa_public_key_derive (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub, + const char *label, + const char *context, + struct GNUNET_CRYPTO_EcdsaPublicKey *result); /** - * Extract the public key for the given private key. + * Output the given MPI value to the given buffer in network + * byte order. The MPI @a val may not be negative. * - * @param priv the private key - * @param pub where to write the public key + * @param buf where to output to + * @param size number of bytes in @a buf + * @param val value to write to @a buf */ void -GNUNET_CRYPTO_ecc_key_get_public (const struct GNUNET_CRYPTO_EccPrivateKey *priv, - struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded *pub); +GNUNET_CRYPTO_mpi_print_unsigned (void *buf, + size_t size, + gcry_mpi_t val); + /** - * Convert a public key to a string. + * Convert data buffer into MPI value. + * The buffer is interpreted as network + * byte order, unsigned integer. * - * @param pub key to convert - * @return string representing 'pub' + * @param result where to store MPI value (allocated) + * @param data raw data (GCRYMPI_FMT_USG) + * @param size number of bytes in @a data */ -char * -GNUNET_CRYPTO_ecc_public_key_to_string (const struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded *pub); +void +GNUNET_CRYPTO_mpi_scan_unsigned (gcry_mpi_t *result, + const void *data, + size_t size); /** - * Convert a string representing a public key to a public key. + * Create a freshly generated paillier public key. * - * @param enc encoded public key - * @param enclen number of bytes in enc (without 0-terminator) - * @param pub where to store the public key - * @return GNUNET_OK on success + * @param[out] public_key Where to store the public key? + * @param[out] private_key Where to store the private key? + */ +void +GNUNET_CRYPTO_paillier_create (struct GNUNET_CRYPTO_PaillierPublicKey *public_key, + struct GNUNET_CRYPTO_PaillierPrivateKey *private_key); + + +/** + * Encrypt a plaintext with a paillier public key. + * + * @param public_key Public key to use. + * @param m Plaintext to encrypt. + * @param desired_ops How many homomorphic ops the caller intends to use + * @param[out] ciphertext Encrytion of @a plaintext with @a public_key. + * @return guaranteed number of supported homomorphic operations >= 1, + * or desired_ops, in case that is lower, + * or -1 if less than one homomorphic operation is possible + */ +int +GNUNET_CRYPTO_paillier_encrypt (const struct GNUNET_CRYPTO_PaillierPublicKey *public_key, + const gcry_mpi_t m, + int desired_ops, + struct GNUNET_CRYPTO_PaillierCiphertext *ciphertext); + + +/** + * Decrypt a paillier ciphertext with a private key. + * + * @param private_key Private key to use for decryption. + * @param public_key Public key to use for decryption. + * @param ciphertext Ciphertext to decrypt. + * @param[out] m Decryption of @a ciphertext with @private_key. + */ +void +GNUNET_CRYPTO_paillier_decrypt (const struct GNUNET_CRYPTO_PaillierPrivateKey *private_key, + const struct GNUNET_CRYPTO_PaillierPublicKey *public_key, + const struct GNUNET_CRYPTO_PaillierCiphertext *ciphertext, + gcry_mpi_t m); + + +/** + * Compute a ciphertext that represents the sum of the plaintext in @a x1 and @a x2 + * + * Note that this operation can only be done a finite number of times + * before an overflow occurs. + * + * @param public_key Public key to use for encryption. + * @param c1 Paillier cipher text. + * @param c2 Paillier cipher text. + * @param[out] result Result of the homomorphic operation. + * @return #GNUNET_OK if the result could be computed, + * #GNUNET_SYSERR if no more homomorphic operations are remaining. + */ +int +GNUNET_CRYPTO_paillier_hom_add (const struct GNUNET_CRYPTO_PaillierPublicKey *public_key, + const struct GNUNET_CRYPTO_PaillierCiphertext *c1, + const struct GNUNET_CRYPTO_PaillierCiphertext *c2, + struct GNUNET_CRYPTO_PaillierCiphertext *result); + + +/** + * Get the number of remaining supported homomorphic operations. + * + * @param c Paillier cipher text. + * @return the number of remaining homomorphic operations */ int -GNUNET_CRYPTO_ecc_public_key_from_string (const char *enc, - size_t enclen, - struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded *pub); +GNUNET_CRYPTO_paillier_hom_get_remaining (const struct GNUNET_CRYPTO_PaillierCiphertext *c); + + +/* ********* Chaum-style RSA-based blind signatures ******************* */ + + + + +/** + * The private information of an RSA key pair. + */ +struct GNUNET_CRYPTO_RsaPrivateKey; + +/** + * The public information of an RSA key pair. + */ +struct GNUNET_CRYPTO_RsaPublicKey; + +/** + * Constant-size pre-secret for blinding key generation. + */ +struct GNUNET_CRYPTO_RsaBlindingKeySecret +{ + /** + * Bits used to generate the blinding key. 256 bits + * of entropy is enough. + */ + uint32_t pre_secret[8] GNUNET_PACKED; +}; + +/** + * @brief an RSA signature + */ +struct GNUNET_CRYPTO_RsaSignature; + + +/** + * Create a new private key. Caller must free return value. + * + * @param len length of the key in bits (i.e. 2048) + * @return fresh private key + */ +struct GNUNET_CRYPTO_RsaPrivateKey * +GNUNET_CRYPTO_rsa_private_key_create (unsigned int len); + + +/** + * Free memory occupied by the private key. + * + * @param key pointer to the memory to free + */ +void +GNUNET_CRYPTO_rsa_private_key_free (struct GNUNET_CRYPTO_RsaPrivateKey *key); /** * Encode the private key in a format suitable for * storing it into a file. * - * @param key key to encode - * @return encoding of the private key. - * The first 4 bytes give the size of the array, as usual. + * @param key the private key + * @param[out] buffer set to a buffer with the encoded key + * @return size of memory allocatedin @a buffer */ -struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded * -GNUNET_CRYPTO_ecc_encode_key (const struct GNUNET_CRYPTO_EccPrivateKey *key); +size_t +GNUNET_CRYPTO_rsa_private_key_encode (const struct GNUNET_CRYPTO_RsaPrivateKey *key, + char **buffer); /** - * Decode the private key from the file-format back + * Decode the private key from the data-format back * to the "normal", internal format. * * @param buf the buffer where the private key data is stored - * @param len the length of the data in 'buffer' - * @param validate GNUNET_YES to validate that the key is well-formed, - * GNUNET_NO if the key comes from a totally trusted source - * and validation is considered too expensive + * @param len the length of the data in @a buf * @return NULL on error */ -struct GNUNET_CRYPTO_EccPrivateKey * -GNUNET_CRYPTO_ecc_decode_key (const char *buf, - size_t len, - int validate); +struct GNUNET_CRYPTO_RsaPrivateKey * +GNUNET_CRYPTO_rsa_private_key_decode (const char *buf, + size_t len); /** - * Create a new private key by reading it from a file. If the - * files does not exist, create a new key and write it to the - * file. Caller must free return value. Note that this function - * can not guarantee that another process might not be trying - * the same operation on the same file at the same time. - * If the contents of the file - * are invalid the old file is deleted and a fresh key is - * created. + * Duplicate the given private key * - * @param filename name of file to use to store the key - * @return new private key, NULL on error (for example, - * permission denied) + * @param key the private key to duplicate + * @return the duplicate key; NULL upon error */ -struct GNUNET_CRYPTO_EccPrivateKey * -GNUNET_CRYPTO_ecc_key_create_from_file (const char *filename); +struct GNUNET_CRYPTO_RsaPrivateKey * +GNUNET_CRYPTO_rsa_private_key_dup (const struct GNUNET_CRYPTO_RsaPrivateKey *key); /** - * Create a new private key by reading our peer's key from - * the file specified in the configuration. + * Extract the public key of the given private key. * - * @return new private key, NULL on error (for example, - * permission denied) + * @param priv the private key + * @retur NULL on error, otherwise the public key */ -struct GNUNET_CRYPTO_EccPrivateKey * -GNUNET_CRYPTO_ecc_key_create_from_configuration (const struct GNUNET_CONFIGURATION_Handle *cfg); +struct GNUNET_CRYPTO_RsaPublicKey * +GNUNET_CRYPTO_rsa_private_key_get_public (const struct GNUNET_CRYPTO_RsaPrivateKey *priv); /** - * Create a new private key. Caller must free return value. Blocking version - * (blocks to gather entropy). + * Compute hash over the public key. * - * @return fresh private key + * @param key public key to hash + * @param hc where to store the hash code */ -struct GNUNET_CRYPTO_EccPrivateKey * -GNUNET_CRYPTO_ecc_key_create (void); +void +GNUNET_CRYPTO_rsa_public_key_hash (const struct GNUNET_CRYPTO_RsaPublicKey *key, + struct GNUNET_HashCode *hc); /** - * Setup a hostkey file for a peer given the name of the - * configuration file (!). This function is used so that - * at a later point code can be certain that reading a - * hostkey is fast (for example in time-dependent testcases). + * Obtain the length of the RSA key in bits. * - * @param cfg_name name of the configuration file to use + * @param key the public key to introspect + * @return length of the key in bits + */ +unsigned int +GNUNET_CRYPTO_rsa_public_key_len (const struct GNUNET_CRYPTO_RsaPublicKey *key); + + +/** + * Free memory occupied by the public key. + * + * @param key pointer to the memory to free */ void -GNUNET_CRYPTO_ecc_setup_hostkey (const char *cfg_name); +GNUNET_CRYPTO_rsa_public_key_free (struct GNUNET_CRYPTO_RsaPublicKey *key); /** - * Retrieve the identity of the host's peer. + * Encode the public key in a format suitable for + * storing it into a file. * - * @param cfg configuration to use - * @param dst pointer to where to write the peer identity - * @return GNUNET_OK on success, GNUNET_SYSERR if the identity - * could not be retrieved + * @param key the private key + * @param[out] buffer set to a buffer with the encoded key + * @return size of memory allocated in @a buffer + */ +size_t +GNUNET_CRYPTO_rsa_public_key_encode (const struct GNUNET_CRYPTO_RsaPublicKey *key, + char **buffer); + + +/** + * Decode the public key from the data-format back + * to the "normal", internal format. + * + * @param buf the buffer where the public key data is stored + * @param len the length of the data in @a buf + * @return NULL on error + */ +struct GNUNET_CRYPTO_RsaPublicKey * +GNUNET_CRYPTO_rsa_public_key_decode (const char *buf, + size_t len); + + +/** + * Duplicate the given public key + * + * @param key the public key to duplicate + * @return the duplicate key; NULL upon error + */ +struct GNUNET_CRYPTO_RsaPublicKey * +GNUNET_CRYPTO_rsa_public_key_dup (const struct GNUNET_CRYPTO_RsaPublicKey *key); + + +/** + * Compare the values of two signatures. + * + * @param s1 one signature + * @param s2 the other signature + * @return 0 if the two are equal */ int -GNUNET_CRYPTO_get_host_identity (const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_PeerIdentity *dst); +GNUNET_CRYPTO_rsa_signature_cmp (struct GNUNET_CRYPTO_RsaSignature *s1, + struct GNUNET_CRYPTO_RsaSignature *s2); + +/** + * Compare the values of two private keys. + * + * @param p1 one private key + * @param p2 the other private key + * @return 0 if the two are equal + */ +int +GNUNET_CRYPTO_rsa_private_key_cmp (struct GNUNET_CRYPTO_RsaPrivateKey *p1, + struct GNUNET_CRYPTO_RsaPrivateKey *p2); /** - * Derive key material from a public and a private ECC key. + * Compare the values of two public keys. * - * @param key private key to use for the ECDH (x) - * @param pub public key to use for the ECDY (yG) - * @param key_material where to write the key material (xyG) - * @return GNUNET_SYSERR on error, GNUNET_OK on success + * @param p1 one public key + * @param p2 the other public key + * @return 0 if the two are equal */ int -GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EccPrivateKey *key, - const struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded *pub, - struct GNUNET_HashCode *key_material); +GNUNET_CRYPTO_rsa_public_key_cmp (struct GNUNET_CRYPTO_RsaPublicKey *p1, + struct GNUNET_CRYPTO_RsaPublicKey *p2); /** - * Sign a given block. + * Blinds the given message with the given blinding key * - * @param key private key to use for the signing - * @param purpose what to sign (size, purpose) - * @param sig where to write the signature - * @return GNUNET_SYSERR on error, GNUNET_OK on success + * @param hash hash of the message to sign + * @param bkey the blinding key + * @param pkey the public key of the signer + * @param[out] buf set to a buffer with the blinded message to be signed + * @param[out] buf_size number of bytes stored in @a buf + * @return GNUNET_YES if successful, GNUNET_NO if RSA key is malicious */ int -GNUNET_CRYPTO_ecc_sign (const struct GNUNET_CRYPTO_EccPrivateKey *key, - const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, - struct GNUNET_CRYPTO_EccSignature *sig); +GNUNET_CRYPTO_rsa_blind (const struct GNUNET_HashCode *hash, + const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks, + struct GNUNET_CRYPTO_RsaPublicKey *pkey, + char **buf, size_t *buf_size); /** - * Verify signature. + * Sign a blinded value, which must be a full domain hash of a message. * - * @param purpose what is the purpose that the signature should have? - * @param validate block to validate (size, purpose, data) + * @param key private key to use for the signing + * @param msg the (blinded) message to sign + * @param msg_len number of bytes in @a msg to sign + * @return NULL on error, signature on success + */ +struct GNUNET_CRYPTO_RsaSignature * +GNUNET_CRYPTO_rsa_sign_blinded (const struct GNUNET_CRYPTO_RsaPrivateKey *key, + const void *msg, size_t msg_len); + + +/** + * Create and sign a full domain hash of a message. + * + * @param key private key to use for the signing + * @param hash the hash of the message to sign + * @return NULL on error, including a malicious RSA key, signature on success + */ +struct GNUNET_CRYPTO_RsaSignature * +GNUNET_CRYPTO_rsa_sign_fdh (const struct GNUNET_CRYPTO_RsaPrivateKey *key, + const struct GNUNET_HashCode *hash); + + +/** + * Free memory occupied by signature. + * + * @param sig memory to free + */ +void +GNUNET_CRYPTO_rsa_signature_free (struct GNUNET_CRYPTO_RsaSignature *sig); + + +/** + * Encode the given signature in a format suitable for storing it into a file. + * + * @param sig the signature + * @param[out] buffer set to a buffer with the encoded key + * @return size of memory allocated in @a buffer + */ +size_t +GNUNET_CRYPTO_rsa_signature_encode (const struct GNUNET_CRYPTO_RsaSignature *sig, + char **buffer); + + +/** + * Decode the signature from the data-format back to the "normal", internal + * format. + * + * @param buf the buffer where the public key data is stored + * @param len the length of the data in @a buf + * @return NULL on error + */ +struct GNUNET_CRYPTO_RsaSignature * +GNUNET_CRYPTO_rsa_signature_decode (const char *buf, + size_t len); + + +/** + * Duplicate the given rsa signature + * + * @param sig the signature to duplicate + * @return the duplicate key; NULL upon error + */ +struct GNUNET_CRYPTO_RsaSignature * +GNUNET_CRYPTO_rsa_signature_dup (const struct GNUNET_CRYPTO_RsaSignature *sig); + + +/** + * Unblind a blind-signed signature. The signature should have been generated + * with #GNUNET_CRYPTO_rsa_sign() using a hash that was blinded with + * #GNUNET_CRYPTO_rsa_blind(). + * + * @param sig the signature made on the blinded signature purpose + * @param bks the blinding key secret used to blind the signature purpose + * @param pkey the public key of the signer + * @return unblinded signature on success, NULL if RSA key is bad or malicious. + */ +struct GNUNET_CRYPTO_RsaSignature * +GNUNET_CRYPTO_rsa_unblind (struct GNUNET_CRYPTO_RsaSignature *sig, + const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks, + struct GNUNET_CRYPTO_RsaPublicKey *pkey); + + +/** + * Verify whether the given hash corresponds to the given signature and the + * signature is valid with respect to the given public key. + * + * @param hash the message to verify to match the @a sig * @param sig signature that is being validated - * @param publicKey public key of the signer - * @returns GNUNET_OK if ok, GNUNET_SYSERR if invalid + * @param public_key public key of the signer + * @returns #GNUNET_YES if ok, #GNUNET_NO if RSA key is malicious, #GNUNET_SYSERR if signature */ int -GNUNET_CRYPTO_ecc_verify (uint32_t purpose, - const struct GNUNET_CRYPTO_EccSignaturePurpose - *validate, - const struct GNUNET_CRYPTO_EccSignature *sig, - const struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded - *publicKey); +GNUNET_CRYPTO_rsa_verify (const struct GNUNET_HashCode *hash, + const struct GNUNET_CRYPTO_RsaSignature *sig, + const struct GNUNET_CRYPTO_RsaPublicKey *public_key); #if 0 /* keep Emacsens' auto-indent happy */