GNUnet 0.21.1
crypto_ecc.c File Reference

public key cryptography (ECC) with libgcrypt More...

#include "platform.h"
#include <gcrypt.h>
#include <sodium.h>
#include "gnunet_util_lib.h"
#include "benchmark.h"
Include dependency graph for crypto_ecc.c:

Go to the source code of this file.

Macros

#define EXTRA_CHECKS   0
 
#define CURVE   "Ed25519"
 IMPLEMENTATION NOTICE: More...
 
#define LOG(kind, ...)   GNUNET_log_from (kind, "util-crypto-ecc", __VA_ARGS__)
 
#define LOG_STRERROR(kind, syscall)    GNUNET_log_from_strerror (kind, "util-crypto-ecc", syscall)
 
#define LOG_STRERROR_FILE(kind, syscall, filename)
 
#define LOG_GCRY(level, cmd, rc)
 Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the message given by gcry_strerror(rc). More...
 

Functions

static int key_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp, const char *topname, const char *elems)
 Extract values from an S-expression. More...
 
static gcry_sexp_t decode_private_ecdsa_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
 Convert the given private key from the network format to the S-expression that can be used by libgcrypt. More...
 
void GNUNET_CRYPTO_ecdsa_key_get_public (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
 Extract the public key for the given private key. More...
 
void GNUNET_CRYPTO_eddsa_key_get_public (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, struct GNUNET_CRYPTO_EddsaPublicKey *pub)
 Extract the public key for the given private key. More...
 
void GNUNET_CRYPTO_ecdhe_key_get_public (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv, struct GNUNET_CRYPTO_EcdhePublicKey *pub)
 Extract the public key for the given private key. More...
 
char * GNUNET_CRYPTO_ecdsa_public_key_to_string (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
 Convert a public key to a string. More...
 
char * GNUNET_CRYPTO_eddsa_public_key_to_string (const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
 Convert a public key to a string. More...
 
char * GNUNET_CRYPTO_eddsa_private_key_to_string (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
 Convert a private key to a string. More...
 
char * GNUNET_CRYPTO_ecdsa_private_key_to_string (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
 Convert a private key to a string. More...
 
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_ecdsa_public_key_from_string (const char *enc, size_t enclen, struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
 Convert a string representing a public key to a public key. More...
 
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_public_key_from_string (const char *enc, size_t enclen, struct GNUNET_CRYPTO_EddsaPublicKey *pub)
 Convert a string representing a public key to a public key. More...
 
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_private_key_from_string (const char *enc, size_t enclen, struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
 Convert a string representing a private key to a private key. More...
 
static void buffer_clear (void *buf, size_t len)
 
void GNUNET_CRYPTO_ecdhe_key_clear (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
 Clear memory that was used to store a private key. More...
 
void GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
 Clear memory that was used to store a private key. More...
 
void GNUNET_CRYPTO_eddsa_key_clear (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
 Clear memory that was used to store a private key. More...
 
void GNUNET_CRYPTO_ecdhe_key_create (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
 Create a new private key. More...
 
void GNUNET_CRYPTO_ecdsa_key_create (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
 Create a new private key. More...
 
void GNUNET_CRYPTO_eddsa_key_create (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
 Create a new private key. More...
 
const struct GNUNET_CRYPTO_EcdsaPrivateKeyGNUNET_CRYPTO_ecdsa_key_get_anonymous ()
 Get the shared private key we use for anonymous users. More...
 
static gcry_sexp_t data_to_ecdsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
 Convert the data specified in the given purpose argument to an S-expression suitable for signature operations. More...
 
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_ecdsa_sign_ (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_CRYPTO_EcdsaSignature *sig)
 ECDSA Sign a given block. More...
 
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_sign_raw (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, void *data, size_t size, struct GNUNET_CRYPTO_EddsaSignature *sig)
 
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_sign_ (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_CRYPTO_EddsaSignature *sig)
 EdDSA sign a given block. More...
 
enum GNUNET_GenericReturnValue 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)
 Verify ECDSA signature. More...
 
enum GNUNET_GenericReturnValue 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)
 Verify EdDSA signature. More...
 
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv, const struct GNUNET_CRYPTO_EcdhePublicKey *pub, struct GNUNET_HashCode *key_material)
 Derive key material from a public and a private ECC key. More...
 
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_EcdhePublicKey *pub, struct GNUNET_HashCode *key_material)
 Derive key material from a ECDH public key and a private EdDSA key. More...
 
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_kem_decaps (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_EcdhePublicKey *c, struct GNUNET_HashCode *key_material)
 Decapsulate a key for a private EdDSA key. More...
 
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_ecdsa_ecdh (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, const struct GNUNET_CRYPTO_EcdhePublicKey *pub, struct GNUNET_HashCode *key_material)
 Derive key material from a ECDH public key and a private ECDSA key. More...
 
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv, const struct GNUNET_CRYPTO_EddsaPublicKey *pub, struct GNUNET_HashCode *key_material)
 Derive key material from a EdDSA public key and a private ECDH key. More...
 
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_kem_encaps (const struct GNUNET_CRYPTO_EddsaPublicKey *pub, struct GNUNET_CRYPTO_EcdhePublicKey *c, struct GNUNET_HashCode *key_material)
 Encapsulate key material for a EdDSA public key. More...
 
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_ecdsa_fo_kem_encaps (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub, struct GNUNET_CRYPTO_FoKemC *c, struct GNUNET_HashCode *key_material)
 Encapsulate key material using a CCA-secure KEM. More...
 
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_fo_kem_encaps (const struct GNUNET_CRYPTO_EddsaPublicKey *pub, struct GNUNET_CRYPTO_FoKemC *c, struct GNUNET_HashCode *key_material)
 Encapsulate key material using a CCA-secure KEM. More...
 
static enum GNUNET_GenericReturnValue fo_kem_decaps (const struct GNUNET_HashCode *w, const struct GNUNET_CRYPTO_FoKemC *c, struct GNUNET_HashCode *key_material)
 
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_fo_kem_decaps (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_FoKemC *c, struct GNUNET_HashCode *key_material)
 This implementation is not testes/publicly exposed yet. More...
 
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_ecdsa_fo_kem_decaps (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, struct GNUNET_CRYPTO_FoKemC *c, struct GNUNET_HashCode *key_material)
 Decapsulate key material using a CCA-secure KEM. More...
 
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_ecdh_ecdsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv, const struct GNUNET_CRYPTO_EcdsaPublicKey *pub, struct GNUNET_HashCode *key_material)
 Derive key material from a EcDSA public key and a private ECDH key. More...
 

Detailed Description

public key cryptography (ECC) with libgcrypt

Author
Christian Grothoff
Florian Dold

Definition in file crypto_ecc.c.

Macro Definition Documentation

◆ EXTRA_CHECKS

#define EXTRA_CHECKS   0

Definition at line 34 of file crypto_ecc.c.

◆ CURVE

#define CURVE   "Ed25519"

IMPLEMENTATION NOTICE:

ECDSA: We use a non-standard curve for ECDSA: Ed25519. For performance reasons, we use cryptographic operations from libsodium wherever we can get away with it, even though libsodium itself does not support ECDSA. This is why the sign and verifiy functionality from libgcrypt is required and used.

EdDSA: We use a standard EdDSA construction. (We still use libgcrypt for hashing and RNG, but not EC)

ECDHE: For both EdDSA and ECDSA keys, we use libsodium for ECDHE due to performance benefits over libgcrypt. Name of the curve we are using. Note that we have hard-coded structs that use 256 bits, so using a bigger curve will require changes that break stuff badly. The name of the curve given here must be agreed by all peers and be supported by libgcrypt.

Definition at line 59 of file crypto_ecc.c.

◆ LOG

#define LOG (   kind,
  ... 
)    GNUNET_log_from (kind, "util-crypto-ecc", __VA_ARGS__)

Definition at line 61 of file crypto_ecc.c.

◆ LOG_STRERROR

#define LOG_STRERROR (   kind,
  syscall 
)     GNUNET_log_from_strerror (kind, "util-crypto-ecc", syscall)

Definition at line 63 of file crypto_ecc.c.

◆ LOG_STRERROR_FILE

#define LOG_STRERROR_FILE (   kind,
  syscall,
  filename 
)
Value:
GNUNET_log_from_strerror_file (kind, "util-crypto-ecc", syscall, \
static char * filename
#define GNUNET_log_from_strerror_file(level, component, cmd, filename)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...

Definition at line 66 of file crypto_ecc.c.

◆ LOG_GCRY

#define LOG_GCRY (   level,
  cmd,
  rc 
)
Value:
do \
{ \
LOG (level, \
_ ("`%s' failed at %s:%d with error: %s\n"), \
cmd, \
__FILE__, \
__LINE__, \
gcry_strerror (rc)); \
} while (0)
#define _(String)
GNU gettext support macro.
Definition: platform.h:178

Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the message given by gcry_strerror(rc).

Definition at line 75 of file crypto_ecc.c.

Function Documentation

◆ key_from_sexp()

static int key_from_sexp ( gcry_mpi_t *  array,
gcry_sexp_t  sexp,
const char *  topname,
const char *  elems 
)
static

Extract values from an S-expression.

Parameters
arraywhere to store the result(s)
sexpS-expression to parse
topnametop-level name in the S-expression that is of interest
elemsnames of the elements to extract
Returns
0 on success

Definition at line 97 of file crypto_ecc.c.

101{
102 gcry_sexp_t list;
103 gcry_sexp_t l2;
104 unsigned int idx;
105
106 list = gcry_sexp_find_token (sexp, topname, 0);
107 if (! list)
108 return 1;
109 l2 = gcry_sexp_cadr (list);
110 gcry_sexp_release (list);
111 list = l2;
112 if (! list)
113 return 2;
114
115 idx = 0;
116 for (const char *s = elems; *s; s++, idx++)
117 {
118 l2 = gcry_sexp_find_token (list, s, 1);
119 if (! l2)
120 {
121 for (unsigned int i = 0; i < idx; i++)
122 {
123 gcry_free (array[i]);
124 array[i] = NULL;
125 }
126 gcry_sexp_release (list);
127 return 3; /* required parameter not found */
128 }
129 array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
130 gcry_sexp_release (l2);
131 if (! array[idx])
132 {
133 for (unsigned int i = 0; i < idx; i++)
134 {
135 gcry_free (array[i]);
136 array[i] = NULL;
137 }
138 gcry_sexp_release (list);
139 return 4; /* required parameter is invalid */
140 }
141 }
142 gcry_sexp_release (list);
143 return 0;
144}
static int list
Set if we should print a list of currently running services.
Definition: gnunet-arm.c:69

References list.

Referenced by GNUNET_CRYPTO_ecdsa_sign_().

Here is the caller graph for this function:

◆ decode_private_ecdsa_key()

static gcry_sexp_t decode_private_ecdsa_key ( const struct GNUNET_CRYPTO_EcdsaPrivateKey priv)
static

Convert the given private key from the network format to the S-expression that can be used by libgcrypt.

Parameters
privprivate key to decode
Returns
NULL on error

Definition at line 155 of file crypto_ecc.c.

156{
157 gcry_sexp_t result;
158 int rc;
159 uint8_t d[32];
160
161 for (size_t i = 0; i<32; i++)
162 d[i] = priv->d[31 - i];
163
164 rc = gcry_sexp_build (&result,
165 NULL,
166 "(private-key(ecc(curve \"" CURVE "\")"
167 "(d %b)))",
168 32,
169 d);
170 if (0 != rc)
171 {
172 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
173 GNUNET_assert (0);
174 }
175#if EXTRA_CHECKS
176 if (0 != (rc = gcry_pk_testkey (result)))
177 {
178 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
179 GNUNET_assert (0);
180 }
181#endif
182 return result;
183}
#define CURVE
IMPLEMENTATION NOTICE:
Definition: crypto_ecc.c:59
#define LOG_GCRY(level, cmd, rc)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
Definition: crypto_ecc.c:75
static mp_limb_t d[(((256)+GMP_NUMB_BITS - 1)/GMP_NUMB_BITS)]
static int result
Global testing status.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
@ GNUNET_ERROR_TYPE_ERROR
unsigned char d[256/8]
d is a value mod n, where n has at most 256 bits.

References CURVE, d, GNUNET_CRYPTO_EcdsaPrivateKey::d, GNUNET_assert, GNUNET_ERROR_TYPE_ERROR, LOG_GCRY, and result.

Referenced by GNUNET_CRYPTO_ecdsa_sign_().

Here is the caller graph for this function:

◆ buffer_clear()

static void buffer_clear ( void *  buf,
size_t  len 
)
static

Definition at line 415 of file crypto_ecc.c.

416{
417#if HAVE_MEMSET_S
418 memset_s (buf, len, 0, len);
419#elif HAVE_EXPLICIT_BZERO
420 explicit_bzero (buf, len);
421#else
422 volatile unsigned char *p = buf;
423 while (len--)
424 *p++ = 0;
425#endif
426}
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-uri.c:38

References p.

Referenced by GNUNET_CRYPTO_ecdhe_key_clear(), GNUNET_CRYPTO_ecdsa_key_clear(), and GNUNET_CRYPTO_eddsa_key_clear().

Here is the caller graph for this function:

◆ data_to_ecdsa_value()

static gcry_sexp_t data_to_ecdsa_value ( const struct GNUNET_CRYPTO_EccSignaturePurpose purpose)
static

Convert the data specified in the given purpose argument to an S-expression suitable for signature operations.

Parameters
purposedata to convert
Returns
converted s-expression

Definition at line 528 of file crypto_ecc.c.

529{
530 gcry_sexp_t data;
531 int rc;
532 /* Unlike EdDSA, libgcrypt expects a hash for ECDSA. */
533 struct GNUNET_HashCode hc;
534
535 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
536 if (0 != (rc = gcry_sexp_build (&data,
537 NULL,
538 "(data(flags rfc6979)(hash %s %b))",
539 "sha512",
540 (int) sizeof(hc),
541 &hc)))
542 {
543 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
544 return NULL;
545 }
546 return data;
547}
static char * data
The data to insert into the dht.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!...
A 512-bit hashcode.

References data, GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_ERROR, LOG_GCRY, and GNUNET_CRYPTO_EccSignaturePurpose::size.

Referenced by GNUNET_CRYPTO_ecdsa_sign_(), and GNUNET_CRYPTO_ecdsa_verify_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ fo_kem_decaps()

static enum GNUNET_GenericReturnValue fo_kem_decaps ( const struct GNUNET_HashCode w,
const struct GNUNET_CRYPTO_FoKemC c,
struct GNUNET_HashCode key_material 
)
static

Definition at line 890 of file crypto_ecc.c.

893{
894 struct GNUNET_HashCode x;
895 struct GNUNET_HashCode ux;
897 struct GNUNET_CRYPTO_EcdhePublicKey pub_test;
898
899 // w xor x (one-time pad)
900 GNUNET_CRYPTO_hash_xor (w, &c->y, &x);
901
902 // We build our OWTF using a FO-transformation of ElGamal:
903 // U(x)
904 GNUNET_CRYPTO_hash (&x, sizeof (x), &ux);
905 GNUNET_memcpy (&sk, &ux, sizeof (sk));
906
907 // B := g^U(x)
908 GNUNET_CRYPTO_ecdhe_key_get_public (&sk, &pub_test);
909
910 if (0 != memcmp (&pub_test, &c->pub, sizeof (c->pub)))
911 return GNUNET_SYSERR; // Reject
912
913 // k := H(x) FIXME: U and H must be different?
914 GNUNET_memcpy (key_material, &ux, sizeof (ux));
915 return GNUNET_OK;
916}
void GNUNET_CRYPTO_ecdhe_key_get_public(const struct GNUNET_CRYPTO_EcdhePrivateKey *priv, struct GNUNET_CRYPTO_EcdhePublicKey *pub)
Extract the public key for the given private key.
Definition: crypto_ecc.c:214
void GNUNET_CRYPTO_hash_xor(const struct GNUNET_HashCode *a, const struct GNUNET_HashCode *b, struct GNUNET_HashCode *result)
compute result = a ^ b
Definition: crypto_hash.c:135
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_OK
@ GNUNET_SYSERR
Private ECC key encoded for transmission.
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and encr...
struct GNUNET_CRYPTO_EcdhePublicKey pub
struct GNUNET_HashCode y

References GNUNET_CRYPTO_ecdhe_key_get_public(), GNUNET_CRYPTO_hash(), GNUNET_CRYPTO_hash_xor(), GNUNET_memcpy, GNUNET_OK, GNUNET_SYSERR, GNUNET_CRYPTO_FoKemC::pub, and GNUNET_CRYPTO_FoKemC::y.

Referenced by GNUNET_CRYPTO_ecdsa_fo_kem_decaps(), and GNUNET_CRYPTO_eddsa_fo_kem_decaps().

Here is the call graph for this function:
Here is the caller graph for this function: