aboutsummaryrefslogtreecommitdiff
path: root/src/util/crypto_cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/crypto_cs.c')
-rw-r--r--src/util/crypto_cs.c214
1 files changed, 66 insertions, 148 deletions
diff --git a/src/util/crypto_cs.c b/src/util/crypto_cs.c
index c89ba5d83..4c6648229 100644
--- a/src/util/crypto_cs.c
+++ b/src/util/crypto_cs.c
@@ -40,11 +40,6 @@
40 */ 40 */
41 41
42 42
43/**
44 * Create a new random private key.
45 *
46 * @param[out] priv where to write the fresh private key
47 */
48void 43void
49GNUNET_CRYPTO_cs_private_key_generate (struct GNUNET_CRYPTO_CsPrivateKey *priv) 44GNUNET_CRYPTO_cs_private_key_generate (struct GNUNET_CRYPTO_CsPrivateKey *priv)
50{ 45{
@@ -52,16 +47,10 @@ GNUNET_CRYPTO_cs_private_key_generate (struct GNUNET_CRYPTO_CsPrivateKey *priv)
52} 47}
53 48
54 49
55/**
56 * Extract the public key of the given private key.
57 *
58 * @param priv the private key
59 * @param[out] pub where to write the public key
60 */
61void 50void
62GNUNET_CRYPTO_cs_private_key_get_public (const struct 51GNUNET_CRYPTO_cs_private_key_get_public (
63 GNUNET_CRYPTO_CsPrivateKey *priv, 52 const struct GNUNET_CRYPTO_CsPrivateKey *priv,
64 struct GNUNET_CRYPTO_CsPublicKey *pub) 53 struct GNUNET_CRYPTO_CsPublicKey *pub)
65{ 54{
66 GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (pub->point.y, 55 GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (pub->point.y,
67 priv->scalar.d)); 56 priv->scalar.d));
@@ -69,63 +58,40 @@ GNUNET_CRYPTO_cs_private_key_get_public (const struct
69 58
70 59
71/** 60/**
72 * maps 32 random bytes to a scalar 61 * Maps 32 random bytes to a scalar. This is necessary because libsodium
73 * this is necessary because libsodium expects scalar to be in the prime order subgroup 62 * expects scalar to be in the prime order subgroup.
74 * @param[out] scalar containing 32 byte char array, is modified to be in prime order subgroup 63 *
64 * @param[in,out] scalar containing 32 byte char array, is modified to be in prime order subgroup
75 */ 65 */
76static void 66static void
77map_to_scalar_subgroup (struct GNUNET_CRYPTO_Cs25519Scalar *scalar) 67map_to_scalar_subgroup (struct GNUNET_CRYPTO_Cs25519Scalar *scalar)
78{ 68{
79 // perform clamping as described in RFC7748 69 /* perform clamping as described in RFC7748 */
80 scalar->d[0] &= 248; 70 scalar->d[0] &= 248;
81 scalar->d[31] &= 127; 71 scalar->d[31] &= 127;
82 scalar->d[31] |= 64; 72 scalar->d[31] |= 64;
83} 73}
84 74
85 75
86/**
87 * Derive a new secret r pair r0 and r1.
88 * In original papers r is generated randomly
89 * To provide abort-idempotency, r needs to be derived but still needs to be UNPREDICTABLE
90 * To ensure unpredictability a new nonce should be used when a new r needs to be derived.
91 * Uses HKDF internally.
92 * Comment: Can be done in one HKDF shot and split output.
93 *
94 * @param nonce is a random nonce
95 * @param lts is a long-term-secret in form of a private key
96 * @param[out] r array containing derived secrets r0 and r1
97 */
98void 76void
99GNUNET_CRYPTO_cs_r_derive (const struct GNUNET_CRYPTO_CsNonce *nonce, 77GNUNET_CRYPTO_cs_r_derive (const struct GNUNET_CRYPTO_CsNonce *nonce,
78 const char *seed,
100 const struct GNUNET_CRYPTO_CsPrivateKey *lts, 79 const struct GNUNET_CRYPTO_CsPrivateKey *lts,
101 struct GNUNET_CRYPTO_CsRSecret r[2]) 80 struct GNUNET_CRYPTO_CsRSecret r[2])
102{ 81{
103 GNUNET_assert (GNUNET_YES == 82 GNUNET_assert (
104 GNUNET_CRYPTO_hkdf (r, 83 GNUNET_YES ==
105 sizeof (struct GNUNET_CRYPTO_CsRSecret) 84 GNUNET_CRYPTO_kdf (
106 * 2, 85 r, sizeof (struct GNUNET_CRYPTO_CsRSecret) * 2,
107 GCRY_MD_SHA512, 86 seed, strlen (seed),
108 GCRY_MD_SHA256, 87 lts, sizeof (*lts),
109 "r", 88 nonce, sizeof (*nonce),
110 strlen ("r"), 89 NULL, 0));
111 lts,
112 sizeof (*lts),
113 nonce,
114 sizeof (*nonce),
115 NULL,
116 0));
117
118 map_to_scalar_subgroup (&r[0].scalar); 90 map_to_scalar_subgroup (&r[0].scalar);
119 map_to_scalar_subgroup (&r[1].scalar); 91 map_to_scalar_subgroup (&r[1].scalar);
120} 92}
121 93
122 94
123/**
124 * Extract the public R of the given secret r.
125 *
126 * @param r_priv the private key
127 * @param[out] r_pub where to write the public key
128 */
129void 95void
130GNUNET_CRYPTO_cs_r_get_public (const struct GNUNET_CRYPTO_CsRSecret *r_priv, 96GNUNET_CRYPTO_cs_r_get_public (const struct GNUNET_CRYPTO_CsRSecret *r_priv,
131 struct GNUNET_CRYPTO_CsRPublic *r_pub) 97 struct GNUNET_CRYPTO_CsRPublic *r_pub)
@@ -135,36 +101,23 @@ GNUNET_CRYPTO_cs_r_get_public (const struct GNUNET_CRYPTO_CsRSecret *r_priv,
135} 101}
136 102
137 103
138/**
139 * Derives new random blinding factors.
140 * In original papers blinding factors are generated randomly
141 * To provide abort-idempotency, blinding factors need to be derived but still need to be UNPREDICTABLE
142 * To ensure unpredictability a new nonce has to be used.
143 * Uses HKDF internally
144 *
145 * @param secret is secret to derive blinding factors
146 * @param secret_len secret length
147 * @param[out] bs array containing the two derived blinding secrets
148 */
149void 104void
150GNUNET_CRYPTO_cs_blinding_secrets_derive (const struct 105GNUNET_CRYPTO_cs_blinding_secrets_derive (
151 GNUNET_CRYPTO_CsNonce *blind_seed, 106 const struct GNUNET_CRYPTO_CsNonce *blind_seed,
152 struct GNUNET_CRYPTO_CsBlindingSecret 107 struct GNUNET_CRYPTO_CsBlindingSecret bs[2])
153 bs[2])
154{ 108{
155 GNUNET_assert (GNUNET_YES == 109 GNUNET_assert (
156 GNUNET_CRYPTO_hkdf (bs, 110 GNUNET_YES ==
157 sizeof (struct 111 GNUNET_CRYPTO_hkdf (bs,
158 GNUNET_CRYPTO_CsBlindingSecret) 112 sizeof (struct GNUNET_CRYPTO_CsBlindingSecret) * 2,
159 * 2, 113 GCRY_MD_SHA512,
160 GCRY_MD_SHA512, 114 GCRY_MD_SHA256,
161 GCRY_MD_SHA256, 115 "alphabeta",
162 "alphabeta", 116 strlen ("alphabeta"),
163 strlen ("alphabeta"), 117 blind_seed,
164 blind_seed, 118 sizeof(*blind_seed),
165 sizeof(*blind_seed), 119 NULL,
166 NULL, 120 0));
167 0));
168 map_to_scalar_subgroup (&bs[0].alpha); 121 map_to_scalar_subgroup (&bs[0].alpha);
169 map_to_scalar_subgroup (&bs[0].beta); 122 map_to_scalar_subgroup (&bs[0].beta);
170 map_to_scalar_subgroup (&bs[1].alpha); 123 map_to_scalar_subgroup (&bs[1].alpha);
@@ -205,11 +158,16 @@ cs_full_domain_hash (const struct GNUNET_CRYPTO_CsRPublic *r_dash,
205 memcpy (r_m_concat, r_dash, sizeof(struct GNUNET_CRYPTO_CsRPublic)); 158 memcpy (r_m_concat, r_dash, sizeof(struct GNUNET_CRYPTO_CsRPublic));
206 memcpy (r_m_concat + sizeof(struct GNUNET_CRYPTO_CsRPublic), msg, msg_len); 159 memcpy (r_m_concat + sizeof(struct GNUNET_CRYPTO_CsRPublic), msg, msg_len);
207 struct GNUNET_HashCode prehash; 160 struct GNUNET_HashCode prehash;
208 GNUNET_CRYPTO_hash (r_m_concat, r_m_concat_len, &prehash); 161
162 GNUNET_CRYPTO_hash (r_m_concat,
163 r_m_concat_len,
164 &prehash);
209 165
210 // modulus converted to MPI representation 166 // modulus converted to MPI representation
211 gcry_mpi_t l_mpi; 167 gcry_mpi_t l_mpi;
212 GNUNET_CRYPTO_mpi_scan_unsigned (&l_mpi, L_BIG_ENDIAN, sizeof(L_BIG_ENDIAN)); 168 GNUNET_CRYPTO_mpi_scan_unsigned (&l_mpi,
169 L_BIG_ENDIAN,
170 sizeof(L_BIG_ENDIAN));
213 171
214 // calculate full domain hash 172 // calculate full domain hash
215 gcry_mpi_t c_mpi; 173 gcry_mpi_t c_mpi;
@@ -224,7 +182,9 @@ cs_full_domain_hash (const struct GNUNET_CRYPTO_CsRPublic *r_dash,
224 182
225 // convert c from mpi 183 // convert c from mpi
226 unsigned char c_big_endian[256 / 8]; 184 unsigned char c_big_endian[256 / 8];
227 GNUNET_CRYPTO_mpi_print_unsigned (c_big_endian, sizeof(c_big_endian), c_mpi); 185 GNUNET_CRYPTO_mpi_print_unsigned (c_big_endian,
186 sizeof(c_big_endian),
187 c_mpi);
228 gcry_mpi_release (c_mpi); 188 gcry_mpi_release (c_mpi);
229 for (size_t i = 0; i<32; i++) 189 for (size_t i = 0; i<32; i++)
230 c->scalar.d[i] = c_big_endian[31 - i]; 190 c->scalar.d[i] = c_big_endian[31 - i];
@@ -266,28 +226,15 @@ calc_r_dash (const struct GNUNET_CRYPTO_CsBlindingSecret *bs,
266} 226}
267 227
268 228
269/**
270 * Calculate two blinded c's
271 * Comment: One would be insecure due to Wagner's algorithm solving ROS
272 *
273 * @param bs array of the two blinding factor structs each containing alpha and beta
274 * @param r_pub array of the two signer's nonce R
275 * @param pub the public key of the signer
276 * @param msg the message to blind in preparation for signing
277 * @param msg_len length of message msg
278 * @param[out] blinded_c array of the two blinded c's
279 * @param[out] blinded_r_pub array of the two blinded R
280 */
281void 229void
282GNUNET_CRYPTO_cs_calc_blinded_c (const struct GNUNET_CRYPTO_CsBlindingSecret 230GNUNET_CRYPTO_cs_calc_blinded_c (
283 bs[2], 231 const struct GNUNET_CRYPTO_CsBlindingSecret bs[2],
284 const struct GNUNET_CRYPTO_CsRPublic r_pub[2], 232 const struct GNUNET_CRYPTO_CsRPublic r_pub[2],
285 const struct GNUNET_CRYPTO_CsPublicKey *pub, 233 const struct GNUNET_CRYPTO_CsPublicKey *pub,
286 const void *msg, 234 const void *msg,
287 size_t msg_len, 235 size_t msg_len,
288 struct GNUNET_CRYPTO_CsC blinded_c[2], 236 struct GNUNET_CRYPTO_CsC blinded_c[2],
289 struct GNUNET_CRYPTO_CsRPublic 237 struct GNUNET_CRYPTO_CsRPublic blinded_r_pub[2])
290 blinded_r_pub[2])
291{ 238{
292 // for i 0/1: R'i = Ri + alpha i*G + beta i*pub 239 // for i 0/1: R'i = Ri + alpha i*G + beta i*pub
293 calc_r_dash (&bs[0], &r_pub[0], pub, &blinded_r_pub[0]); 240 calc_r_dash (&bs[0], &r_pub[0], pub, &blinded_r_pub[0]);
@@ -309,30 +256,13 @@ GNUNET_CRYPTO_cs_calc_blinded_c (const struct GNUNET_CRYPTO_CsBlindingSecret
309} 256}
310 257
311 258
312/**
313 * Sign a blinded c
314 * This function derives b from a nonce and a longterm secret
315 * In original papers b is generated randomly
316 * To provide abort-idempotency, b needs to be derived but still need to be UNPREDICTABLE.
317 * To ensure unpredictability a new nonce has to be used for every signature
318 * HKDF is used internally for derivation
319 * r0 and r1 can be derived prior by using GNUNET_CRYPTO_cs_r_derive
320 *
321 * @param priv private key to use for the signing and as LTS in HKDF
322 * @param r array of the two secret nonce from the signer
323 * @param c array of the two blinded c to sign c_b
324 * @param nonce is a random nonce
325 * @param[out] blinded_signature_scalar where to write the signature
326 * @return 0 or 1 for b (see Clause Blind Signature Scheme)
327 */
328unsigned int 259unsigned int
329GNUNET_CRYPTO_cs_sign_derive (const struct GNUNET_CRYPTO_CsPrivateKey *priv, 260GNUNET_CRYPTO_cs_sign_derive (
330 const struct GNUNET_CRYPTO_CsRSecret r[2], 261 const struct GNUNET_CRYPTO_CsPrivateKey *priv,
331 const struct GNUNET_CRYPTO_CsC c[2], 262 const struct GNUNET_CRYPTO_CsRSecret r[2],
332 const struct GNUNET_CRYPTO_CsNonce *nonce, 263 const struct GNUNET_CRYPTO_CsC c[2],
333 struct GNUNET_CRYPTO_CsBlindS * 264 const struct GNUNET_CRYPTO_CsNonce *nonce,
334 blinded_signature_scalar 265 struct GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar)
335 )
336{ 266{
337 uint32_t hkdf_out; 267 uint32_t hkdf_out;
338 268
@@ -365,18 +295,11 @@ GNUNET_CRYPTO_cs_sign_derive (const struct GNUNET_CRYPTO_CsPrivateKey *priv,
365} 295}
366 296
367 297
368/**
369 * Unblind a blind-signed signature using a c that was blinded
370 *
371 * @param blinded_signature_scalar the signature made on the blinded c
372 * @param bs the blinding factors used in the blinding
373 * @param[out] signature_scalar where to write the unblinded signature
374 */
375void 298void
376GNUNET_CRYPTO_cs_unblind (const struct 299GNUNET_CRYPTO_cs_unblind (
377 GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar, 300 const struct GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar,
378 const struct GNUNET_CRYPTO_CsBlindingSecret *bs, 301 const struct GNUNET_CRYPTO_CsBlindingSecret *bs,
379 struct GNUNET_CRYPTO_CsS *signature_scalar) 302 struct GNUNET_CRYPTO_CsS *signature_scalar)
380{ 303{
381 crypto_core_ed25519_scalar_add (signature_scalar->scalar.d, 304 crypto_core_ed25519_scalar_add (signature_scalar->scalar.d,
382 blinded_signature_scalar->scalar.d, 305 blinded_signature_scalar->scalar.d,
@@ -384,16 +307,6 @@ GNUNET_CRYPTO_cs_unblind (const struct
384} 307}
385 308
386 309
387/**
388 * Verify whether the given message corresponds to the given signature and the
389 * signature is valid with respect to the given public key.
390 *
391 * @param sig signature that is being validated
392 * @param pub public key of the signer
393 * @param msg is the message that should be signed by @a sig (message is used to calculate c)
394 * @param msg_len is the message length
395 * @returns #GNUNET_YES on success, #GNUNET_SYSERR if signature invalid
396 */
397enum GNUNET_GenericReturnValue 310enum GNUNET_GenericReturnValue
398GNUNET_CRYPTO_cs_verify (const struct GNUNET_CRYPTO_CsSignature *sig, 311GNUNET_CRYPTO_cs_verify (const struct GNUNET_CRYPTO_CsSignature *sig,
399 const struct GNUNET_CRYPTO_CsPublicKey *pub, 312 const struct GNUNET_CRYPTO_CsPublicKey *pub,
@@ -402,7 +315,12 @@ GNUNET_CRYPTO_cs_verify (const struct GNUNET_CRYPTO_CsSignature *sig,
402{ 315{
403 // calculate c' = H(R, m) 316 // calculate c' = H(R, m)
404 struct GNUNET_CRYPTO_CsC c_dash; 317 struct GNUNET_CRYPTO_CsC c_dash;
405 cs_full_domain_hash (&sig->r_point, msg, msg_len, pub, &c_dash); 318
319 cs_full_domain_hash (&sig->r_point,
320 msg,
321 msg_len,
322 pub,
323 &c_dash);
406 324
407 // s'G ?= R' + c' pub 325 // s'G ?= R' + c' pub
408 struct GNUNET_CRYPTO_Cs25519Point sig_scal_mul_base; 326 struct GNUNET_CRYPTO_Cs25519Point sig_scal_mul_base;