X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Finclude%2Fgnunet_crypto_lib.h;h=a5ee980926c821262856d569117e1efb3584ebab;hb=4e29ecde9b3ad3e34af359f18b6679c06b17ce78;hp=a0935363b3589dee633de5e8f3593dd70bc595a0;hpb=427dd6f998fb1fde515a3b5c800f9f6d308197b2;p=oweals%2Fgnunet.git diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h index a0935363b..0787fdf63 100644 --- a/src/include/gnunet_crypto_lib.h +++ b/src/include/gnunet_crypto_lib.h @@ -1,21 +1,16 @@ /* This file is part of GNUnet. - (C) 2001-2013 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 3, or (at your - option) any later version. + 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 - General Public License for more details. - - 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. + Affero General Public License for more details. */ /** @@ -27,9 +22,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. * - * @defgroup crypto Cryptographic operations - * @defgroup hash Hashing and operations on hashes + * @see [Documentation](https://gnunet.org/crypto-api) */ #ifndef GNUNET_CRYPTO_LIB_H @@ -44,28 +47,34 @@ extern "C" #endif /** - * @brief A 512-bit hashcode - */ -struct GNUNET_HashCode; - -/** - * The identity of the host (wraps the signing key of the peer). + * @brief A 512-bit hashcode. These are the default length for GNUnet, using SHA-512. */ -struct GNUNET_PeerIdentity; +struct GNUNET_HashCode +{ + uint32_t bits[512 / 8 / sizeof (uint32_t)]; /* = 16 */ +}; -#include "gnunet_common.h" -#include "gnunet_scheduler_lib.h" /** - * @brief A 512-bit hashcode + * @brief A 256-bit hashcode. Used under special conditions, like when space + * is critical and security is not impacted by it. */ -struct GNUNET_HashCode +struct GNUNET_ShortHashCode { - uint32_t bits[512 / 8 / sizeof (uint32_t)]; /* = 16 */ + 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 + + /** * Maximum length of an ECC signature. * Note: round up to multiple of 8 minus 2 for alignment. @@ -110,6 +119,12 @@ enum GNUNET_CRYPTO_Quality */ #define GNUNET_CRYPTO_HASH_LENGTH (512/8) +/** + * How many characters (without 0-terminator) are our ASCII-encoded + * public keys (ECDSA/EDDSA/ECDHE). + */ +#define GNUNET_CRYPTO_PKEY_ASCII_LENGTH 52 + /** * @brief 0-terminated ASCII encoding of a struct GNUNET_HashCode. */ @@ -148,9 +163,10 @@ struct GNUNET_CRYPTO_EccSignaturePurpose /** - * @brief an ECC signature + * @brief an ECC signature using EdDSA. + * See https://gnunet.org/ed25519 */ -struct GNUNET_CRYPTO_EccSignature +struct GNUNET_CRYPTO_EddsaSignature { /** @@ -166,66 +182,111 @@ struct GNUNET_CRYPTO_EccSignature }; + /** - * Public ECC key (always for NIST P-521) encoded in a format suitable - * for network transmission and signatures (ECDSA/EdDSA). + * @brief an ECC signature using ECDSA */ -struct GNUNET_CRYPTO_EccPublicSignKey +struct GNUNET_CRYPTO_EcdsaSignature { + + /** + * R value. + */ + unsigned char r[256 / 8]; + /** - * Q consists of an x- and a y-value, each mod p (256 bits), - * given here in affine coordinates. - * - * FIXME: this coordinate will be removed in the future (compressed point!). + * S value. */ - unsigned char q_x[256 / 8]; + unsigned char s[256 / 8]; +}; + + +/** + * Public ECC key (always for Curve25519) encoded in a format suitable + * for network transmission and EdDSA signatures. + */ +struct GNUNET_CRYPTO_EddsaPublicKey +{ /** - * Q consists of an x- and a y-value, each mod p (256 bits), - * given here in affine coordinates. + * 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]; }; +/** + * Public ECC key (always for Curve25519) encoded in a format suitable + * for network transmission and ECDSA signatures. + */ +struct GNUNET_CRYPTO_EcdsaPublicKey +{ + /** + * 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]; + +}; + /** * The identity of the host (wraps the signing key of the peer). */ struct GNUNET_PeerIdentity { - struct GNUNET_CRYPTO_EccPublicSignKey public_key; + struct GNUNET_CRYPTO_EddsaPublicKey public_key; }; /** - * Public ECC key (always for NIST P-521) encoded in a format suitable - * for network transmission and encryption (ECDH). + * 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_EccPublicEncryptKey +struct GNUNET_CRYPTO_EcdhePublicKey { /** - * Q consists of an x- and a y-value, each mod p (256 bits), - * given here in affine coordinates. + * 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_x[256 / 8]; + unsigned char q_y[256 / 8]; +}; + +/** + * Private ECC key encoded for transmission. To be used only for ECDH + * key exchange (ECDHE to be precise). + */ +struct GNUNET_CRYPTO_EcdhePrivateKey +{ /** - * Q consists of an x- and a y-value, each mod p (256 bits), - * given here in affine coordinates. - * - * FIXME: this coordinate will be removed in the future (compressed point!). + * d is a value mod n, where n has at most 256 bits. */ - unsigned char q_y[256 / 8]; + unsigned char d[256 / 8]; }; +/** + * Private ECC key encoded for transmission. To be used only for ECDSA + * signatures. + */ +struct GNUNET_CRYPTO_EcdsaPrivateKey +{ + /** + * d is a value mod n, where n has at most 256 bits. + */ + unsigned char d[256 / 8]; + +}; /** - * Private ECC key encoded for transmission. + * Private ECC key encoded for transmission. To be used only for EdDSA + * signatures. */ -struct GNUNET_CRYPTO_EccPrivateKey +struct GNUNET_CRYPTO_EddsaPrivateKey { /** * d is a value mod n, where n has at most 256 bits. @@ -277,6 +338,59 @@ 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 private 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 ************* */ /** @@ -290,16 +404,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 @a buf, must be multiple of 2 - * @return updated crc sum (must be subjected to GNUNET_CRYPTO_crc16_finish to get actual crc16) + * @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); /** @@ -321,7 +450,10 @@ GNUNET_CRYPTO_crc16_finish (uint32_t sum); * @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); + + /** @@ -334,8 +466,22 @@ GNUNET_CRYPTO_crc16_n (const void *buf, size_t len); * @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 @@ -346,7 +492,8 @@ GNUNET_CRYPTO_crc32_n (const void *buf, size_t len); * @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); /** @@ -358,7 +505,8 @@ GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode, uint32_t i); * @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); /** @@ -371,7 +519,8 @@ GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, uint64_t max); * @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); /** @@ -389,17 +538,18 @@ GNUNET_CRYPTO_symmetric_create_session_key (struct GNUNET_CRYPTO_SymmetricSessio * 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_symmetric_encrypt (const void *block, size_t len, - const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey, - const struct GNUNET_CRYPTO_SymmetricInitializationVector - *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); /** @@ -414,10 +564,11 @@ GNUNET_CRYPTO_symmetric_encrypt (const void *block, size_t len, * @return -1 on failure, size of decrypted block on success */ ssize_t -GNUNET_CRYPTO_symmetric_decrypt (const void *block, size_t size, - const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey, - const struct GNUNET_CRYPTO_SymmetricInitializationVector - *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); /** @@ -426,13 +577,14 @@ GNUNET_CRYPTO_symmetric_decrypt (const void *block, size_t size, * @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_symmetric_derive_iv (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, - const struct GNUNET_CRYPTO_SymmetricSessionKey *skey, - const void *salt, size_t salt_len, ...); + const struct GNUNET_CRYPTO_SymmetricSessionKey *skey, + const void *salt, + size_t salt_len, ...); /** @@ -440,13 +592,15 @@ GNUNET_CRYPTO_symmetric_derive_iv (struct GNUNET_CRYPTO_SymmetricInitializationV * @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_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); + const struct GNUNET_CRYPTO_SymmetricSessionKey *skey, + const void *salt, + size_t salt_len, + va_list argp); /** @@ -457,7 +611,7 @@ GNUNET_CRYPTO_symmetric_derive_iv_v (struct GNUNET_CRYPTO_SymmetricInitializatio * 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); @@ -471,7 +625,8 @@ GNUNET_CRYPTO_hash_to_enc (const struct GNUNET_HashCode * block, * @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, +GNUNET_CRYPTO_hash_from_string2 (const char *enc, + size_t enclen, struct GNUNET_HashCode *result); @@ -491,7 +646,7 @@ GNUNET_CRYPTO_hash_from_string2 (const char *enc, size_t enclen, * @ingroup hash * * Compute the distance between 2 hashcodes. The - * computation must be fast, not involve a[0] or a[4] (they're used + * 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. * @@ -500,8 +655,8 @@ GNUNET_CRYPTO_hash_from_string2 (const char *enc, size_t enclen, * @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); /** @@ -513,7 +668,57 @@ GNUNET_CRYPTO_hash_distance_u32 (const struct GNUNET_HashCode * a, * @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; + + +/** + * Start incremental hashing operation. + * + * @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_hash_context_read (struct GNUNET_HashContext *hc, + const void *buf, + size_t size); + + +/** + * Finish the hash computation. + * + * @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_hash_context_finish (struct GNUNET_HashContext *hc, + struct GNUNET_HashCode *r_hash); + + +/** + * Abort hashing, do not bother calculating final result. + * + * @param hc hash context to destroy + */ +void +GNUNET_CRYPTO_hash_context_abort (struct GNUNET_HashContext *hc); /** @@ -527,8 +732,9 @@ GNUNET_CRYPTO_hash (const void *block, size_t size, struct GNUNET_HashCode * ret */ 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); /** @@ -538,9 +744,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); /** @@ -562,7 +768,8 @@ struct GNUNET_CRYPTO_FileHashContext; */ 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); @@ -590,30 +797,30 @@ GNUNET_CRYPTO_hash_create_random (enum GNUNET_CRYPTO_Quality mode, /** * @ingroup hash - * compute result(delta) = b - a + * compute @a result = @a b - @a a * * @param a some hash code * @param b some hash code * @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); /** * @ingroup hash - * compute result(b) = a + delta + * compute @a result = @a a + @a delta * * @param a some hash code * @param delta some hash code * @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); /** @@ -625,8 +832,9 @@ GNUNET_CRYPTO_hash_sum (const struct GNUNET_HashCode * a, * @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); /** @@ -640,8 +848,7 @@ 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_SymmetricSessionKey *skey, - struct GNUNET_CRYPTO_SymmetricInitializationVector - *iv); + struct GNUNET_CRYPTO_SymmetricInitializationVector *iv); /** @@ -653,14 +860,14 @@ GNUNET_CRYPTO_hash_to_aes_key (const struct GNUNET_HashCode * hc, * @return Bit \a bit from hashcode \a code, -1 for invalid index */ int -GNUNET_CRYPTO_hash_get_bit (const struct GNUNET_HashCode *code, +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!). @@ -670,8 +877,8 @@ GNUNET_CRYPTO_hash_get_bit (const struct GNUNET_HashCode *code, * @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); /** @@ -681,10 +888,11 @@ GNUNET_CRYPTO_hash_matching_bits (const struct GNUNET_HashCode * first, * * @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); /** @@ -695,12 +903,12 @@ GNUNET_CRYPTO_hash_cmp (const struct GNUNET_HashCode * h1, const struct GNUNET_H * @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); /** @@ -731,7 +939,8 @@ 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_SymmetricSessionKey *rkey, - const void *salt, size_t salt_len, ...); + const void *salt, size_t salt_len, + ...); /** @@ -742,16 +951,22 @@ GNUNET_CRYPTO_hmac_derive_key (struct GNUNET_CRYPTO_AuthKey *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, + ...); /** @@ -762,16 +977,22 @@ GNUNET_CRYPTO_hkdf (void *result, size_t out_len, int xtr_algo, int prf_algo, * @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); /** @@ -779,46 +1000,74 @@ 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 */ 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, + ...); /** - * Function called upon completion of 'GNUNET_CRYPTO_ecc_key_create_async'. + * @ingroup crypto + * Extract the public key for the given private key. * - * @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 priv the private key + * @param pub where to write the public key */ -typedef void (*GNUNET_CRYPTO_EccKeyCallback)(void *cls, - struct GNUNET_CRYPTO_EccPrivateKey *pk, - const char *emsg); - +void +GNUNET_CRYPTO_ecdsa_key_get_public (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, + struct GNUNET_CRYPTO_EcdsaPublicKey *pub); /** * @ingroup crypto @@ -828,8 +1077,8 @@ typedef void (*GNUNET_CRYPTO_EccKeyCallback)(void *cls, * @param pub where to write the public key */ void -GNUNET_CRYPTO_ecc_key_get_public_for_signature (const struct GNUNET_CRYPTO_EccPrivateKey *priv, - struct GNUNET_CRYPTO_EccPublicSignKey *pub); +GNUNET_CRYPTO_eddsa_key_get_public (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, + struct GNUNET_CRYPTO_EddsaPublicKey *pub); @@ -841,8 +1090,28 @@ GNUNET_CRYPTO_ecc_key_get_public_for_signature (const struct GNUNET_CRYPTO_EccPr * @param pub where to write the public key */ void -GNUNET_CRYPTO_ecc_key_get_public_for_encryption (const struct GNUNET_CRYPTO_EccPrivateKey *priv, - struct GNUNET_CRYPTO_EccPublicEncryptKey *pub); +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 private key to a string. + * + * @param priv key to convert + * @return string representing @a pub + */ +char * +GNUNET_CRYPTO_eddsa_private_key_to_string (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv); /** @@ -852,7 +1121,7 @@ GNUNET_CRYPTO_ecc_key_get_public_for_encryption (const struct GNUNET_CRYPTO_EccP * @return string representing @a pub */ char * -GNUNET_CRYPTO_ecc_public_sign_key_to_string (const struct GNUNET_CRYPTO_EccPublicSignKey *pub); +GNUNET_CRYPTO_eddsa_public_key_to_string (const struct GNUNET_CRYPTO_EddsaPublicKey *pub); /** @@ -864,20 +1133,23 @@ GNUNET_CRYPTO_ecc_public_sign_key_to_string (const struct GNUNET_CRYPTO_EccPubli * @return #GNUNET_OK on success */ int -GNUNET_CRYPTO_ecc_public_sign_key_from_string (const char *enc, - size_t enclen, - struct GNUNET_CRYPTO_EccPublicSignKey *pub); - +GNUNET_CRYPTO_ecdsa_public_key_from_string (const char *enc, + size_t enclen, + struct GNUNET_CRYPTO_EcdsaPublicKey *pub); /** - * Convert a public key to a string. + * Convert a string representing a private key to a private key. * - * @param pub key to convert - * @return string representing @a pub + * @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 */ -char * -GNUNET_CRYPTO_ecc_public_encrypt_key_to_string (const struct GNUNET_CRYPTO_EccPublicEncryptKey *pub); +int +GNUNET_CRYPTO_eddsa_private_key_from_string (const char *enc, + size_t enclen, + struct GNUNET_CRYPTO_EddsaPrivateKey *pub); /** @@ -889,9 +1161,28 @@ GNUNET_CRYPTO_ecc_public_encrypt_key_to_string (const struct GNUNET_CRYPTO_EccPu * @return #GNUNET_OK on success */ int -GNUNET_CRYPTO_ecc_public_encrypt_key_from_string (const char *enc, - size_t enclen, - struct GNUNET_CRYPTO_EccPublicEncryptKey *pub); +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); /** @@ -909,8 +1200,14 @@ GNUNET_CRYPTO_ecc_public_encrypt_key_from_string (const char *enc, * @return new private key, NULL on error (for example, * permission denied); free using #GNUNET_free */ -struct GNUNET_CRYPTO_EccPrivateKey * -GNUNET_CRYPTO_ecc_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; /** @@ -922,8 +1219,39 @@ GNUNET_CRYPTO_ecc_key_create_from_file (const char *filename); * @return new private key, NULL on error (for example, * permission denied); free using #GNUNET_free */ -struct GNUNET_CRYPTO_EccPrivateKey * -GNUNET_CRYPTO_ecc_key_create_from_configuration (const struct GNUNET_CONFIGURATION_Handle *cfg); +struct GNUNET_CRYPTO_EddsaPrivateKey * +GNUNET_CRYPTO_eddsa_key_create_from_configuration (const struct GNUNET_CONFIGURATION_Handle *cfg); + + +/** + * @ingroup crypto + * Create a new private key. Caller must free return value. + * + * @return fresh private key; free using #GNUNET_free + */ +struct GNUNET_CRYPTO_EcdsaPrivateKey * +GNUNET_CRYPTO_ecdsa_key_create (void); + + +/** + * @ingroup crypto + * Create a new private key. Caller must free return value. + * + * @return fresh private key; free using #GNUNET_free + */ +struct GNUNET_CRYPTO_EddsaPrivateKey * +GNUNET_CRYPTO_eddsa_key_create (void); + + +/** + * @ingroup crypto + * Create a new private key. Clear with #GNUNET_CRYPTO_ecdhe_key_clear(). + * + * @param[out] pk set to fresh private key; + * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure + */ +int +GNUNET_CRYPTO_ecdhe_key_create2 (struct GNUNET_CRYPTO_EcdhePrivateKey *pk); /** @@ -932,18 +1260,38 @@ GNUNET_CRYPTO_ecc_key_create_from_configuration (const struct GNUNET_CONFIGURATI * * @return fresh private key; free using #GNUNET_free */ -struct GNUNET_CRYPTO_EccPrivateKey * -GNUNET_CRYPTO_ecc_key_create (void); +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_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. + * Clear memory that was used to store a private key. * * @param pk location of the key */ void -GNUNET_CRYPTO_ecc_key_clear (struct GNUNET_CRYPTO_EccPrivateKey *pk); +GNUNET_CRYPTO_ecdhe_key_clear (struct GNUNET_CRYPTO_EcdhePrivateKey *pk); /** @@ -952,8 +1300,8 @@ GNUNET_CRYPTO_ecc_key_clear (struct GNUNET_CRYPTO_EccPrivateKey *pk); * * @return "anonymous" private key; do not free */ -const struct GNUNET_CRYPTO_EccPrivateKey * -GNUNET_CRYPTO_ecc_key_get_anonymous (void); +const struct GNUNET_CRYPTO_EcdsaPrivateKey * +GNUNET_CRYPTO_ecdsa_key_get_anonymous (void); /** @@ -962,11 +1310,11 @@ GNUNET_CRYPTO_ecc_key_get_anonymous (void); * 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_ecc_setup_hostkey (const char *cfg_name); +GNUNET_CRYPTO_eddsa_setup_hostkey (const char *cfg_name); /** @@ -979,28 +1327,307 @@ GNUNET_CRYPTO_ecc_setup_hostkey (const char *cfg_name); * could not be retrieved */ int -GNUNET_CRYPTO_get_host_identity (const struct GNUNET_CONFIGURATION_Handle *cfg, +GNUNET_CRYPTO_get_peer_identity (const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_PeerIdentity *dst); /** - * @ingroup crypto - * Derive key material from a public and a private ECC key. + * Compare two Peer Identities. * - * @param priv 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 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_ecc_ecdh (const struct GNUNET_CRYPTO_EccPrivateKey *priv, - const struct GNUNET_CRYPTO_EccPublicEncryptKey *pub, +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_ecc_point_to_bin (struct GNUNET_CRYPTO_EccDlogContext *edc, + gcry_mpi_point_t point, + struct GNUNET_CRYPTO_EccPoint *bin); + + +/** + * Convert binary representation of a point to computational representation. + * + * @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_ecc_rnd (struct GNUNET_CRYPTO_EccDlogContext *edc, + gcry_mpi_point_t *r, + gcry_mpi_point_t *r_inv); + + +/** + * Obtain a random scalar for point multiplication on the curve and + * its multiplicative inverse. + * + * @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_ecc_rnd_mpi (struct GNUNET_CRYPTO_EccDlogContext *edc, + gcry_mpi_t *r, + gcry_mpi_t *r_inv); + + +/** + * Generate a random value mod n. + * + * @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_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv, + const struct GNUNET_CRYPTO_EcdhePublicKey *pub, struct GNUNET_HashCode *key_material); /** * @ingroup crypto - * Sign a given block. + * Derive key material from a ECDH public key and a private EdDSA key. + * Dual to #GNUNET_CRRYPTO_ecdh_eddsa. + * + * @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 + */ +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); + + +/** + * @ingroup crypto + * Derive key material from a EdDSA public key and a private ECDH key. + * Dual to #GNUNET_CRRYPTO_eddsa_ecdh. + * + * @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 + */ +int +GNUNET_CRYPTO_eddsa_sign (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, + const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, + struct GNUNET_CRYPTO_EddsaSignature *sig); + + +/** + * @ingroup crypto + * ECDSA Sign a given block. * * @param priv private key to use for the signing * @param purpose what to sign (size, purpose) @@ -1008,14 +1635,31 @@ GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EccPrivateKey *priv, * @return #GNUNET_SYSERR on error, #GNUNET_OK on success */ int -GNUNET_CRYPTO_ecc_sign (const struct GNUNET_CRYPTO_EccPrivateKey *priv, - const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, - struct GNUNET_CRYPTO_EccSignature *sig); +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 pub public key of the signer + * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid + */ +int +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); + /** * @ingroup crypto - * Verify signature. + * Verify ECDSA signature. * * @param purpose what is the purpose that the signature should have? * @param validate block to validate (size, purpose, data) @@ -1024,11 +1668,10 @@ GNUNET_CRYPTO_ecc_sign (const struct GNUNET_CRYPTO_EccPrivateKey *priv, * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid */ int -GNUNET_CRYPTO_ecc_verify (uint32_t purpose, - const struct GNUNET_CRYPTO_EccSignaturePurpose - *validate, - const struct GNUNET_CRYPTO_EccSignature *sig, - const struct GNUNET_CRYPTO_EccPublicSignKey *pub); +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); /** @@ -1044,10 +1687,10 @@ GNUNET_CRYPTO_ecc_verify (uint32_t purpose, * typically the name of the subsystem/application * @return derived private key */ -struct GNUNET_CRYPTO_EccPrivateKey * -GNUNET_CRYPTO_ecc_key_derive (const struct GNUNET_CRYPTO_EccPrivateKey *priv, - const char *label, - const char *context); +struct GNUNET_CRYPTO_EcdsaPrivateKey * +GNUNET_CRYPTO_ecdsa_private_key_derive (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, + const char *label, + const char *context); /** @@ -1062,10 +1705,431 @@ GNUNET_CRYPTO_ecc_key_derive (const struct GNUNET_CRYPTO_EccPrivateKey *priv, * @param result where to write the derived public key */ void -GNUNET_CRYPTO_ecc_public_key_derive (const struct GNUNET_CRYPTO_EccPublicSignKey *pub, - const char *label, - const char *context, - struct GNUNET_CRYPTO_EccPublicSignKey *result); +GNUNET_CRYPTO_ecdsa_public_key_derive (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub, + const char *label, + const char *context, + struct GNUNET_CRYPTO_EcdsaPublicKey *result); + + +/** + * Output the given MPI value to the given buffer in network + * byte order. The MPI @a val may not be negative. + * + * @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_mpi_print_unsigned (void *buf, + size_t size, + gcry_mpi_t val); + + +/** + * Convert data buffer into MPI value. + * The buffer is interpreted as network + * byte order, unsigned integer. + * + * @param result where to store MPI value (allocated) + * @param data raw data (GCRYMPI_FMT_USG) + * @param size number of bytes in @a data + */ +void +GNUNET_CRYPTO_mpi_scan_unsigned (gcry_mpi_t *result, + const void *data, + size_t size); + + +/** + * Create a freshly generated paillier public key. + * + * @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_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 the private key + * @param[out] buffer set to a buffer with the encoded key + * @return size of memory allocatedin @a buffer + */ +size_t +GNUNET_CRYPTO_rsa_private_key_encode (const struct GNUNET_CRYPTO_RsaPrivateKey *key, + char **buffer); + + +/** + * 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 @a buf + * @return NULL on error + */ +struct GNUNET_CRYPTO_RsaPrivateKey * +GNUNET_CRYPTO_rsa_private_key_decode (const char *buf, + size_t len); + + +/** + * Duplicate the given private key + * + * @param key the private key to duplicate + * @return the duplicate key; NULL upon error + */ +struct GNUNET_CRYPTO_RsaPrivateKey * +GNUNET_CRYPTO_rsa_private_key_dup (const struct GNUNET_CRYPTO_RsaPrivateKey *key); + + +/** + * Extract the public key of the given private key. + * + * @param priv the private key + * @retur NULL on error, otherwise the public key + */ +struct GNUNET_CRYPTO_RsaPublicKey * +GNUNET_CRYPTO_rsa_private_key_get_public (const struct GNUNET_CRYPTO_RsaPrivateKey *priv); + + +/** + * Compute hash over the public key. + * + * @param key public key to hash + * @param hc where to store the hash code + */ +void +GNUNET_CRYPTO_rsa_public_key_hash (const struct GNUNET_CRYPTO_RsaPublicKey *key, + struct GNUNET_HashCode *hc); + + +/** + * Obtain the length of the RSA key in bits. + * + * @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_rsa_public_key_free (struct GNUNET_CRYPTO_RsaPublicKey *key); + + +/** + * Encode the public key in a format suitable for + * storing it into a file. + * + * @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_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); + + +/** + * Compare the values of two public keys. + * + * @param p1 one public key + * @param p2 the other public key + * @return 0 if the two are equal + */ +int +GNUNET_CRYPTO_rsa_public_key_cmp (struct GNUNET_CRYPTO_RsaPublicKey *p1, + struct GNUNET_CRYPTO_RsaPublicKey *p2); + + +/** + * Blinds the given message with the given blinding key + * + * @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_rsa_blind (const struct GNUNET_HashCode *hash, + const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks, + struct GNUNET_CRYPTO_RsaPublicKey *pkey, + char **buf, + size_t *buf_size); + + +/** + * Sign a blinded value, which must be a full domain hash of a message. + * + * @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 (const 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 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_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 */