diff options
Diffstat (limited to 'src/util/crypto_cs.c')
-rw-r--r-- | src/util/crypto_cs.c | 214 |
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 | */ | ||
48 | void | 43 | void |
49 | GNUNET_CRYPTO_cs_private_key_generate (struct GNUNET_CRYPTO_CsPrivateKey *priv) | 44 | GNUNET_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 | */ | ||
61 | void | 50 | void |
62 | GNUNET_CRYPTO_cs_private_key_get_public (const struct | 51 | GNUNET_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 | */ |
76 | static void | 66 | static void |
77 | map_to_scalar_subgroup (struct GNUNET_CRYPTO_Cs25519Scalar *scalar) | 67 | map_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 | */ | ||
98 | void | 76 | void |
99 | GNUNET_CRYPTO_cs_r_derive (const struct GNUNET_CRYPTO_CsNonce *nonce, | 77 | GNUNET_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 | */ | ||
129 | void | 95 | void |
130 | GNUNET_CRYPTO_cs_r_get_public (const struct GNUNET_CRYPTO_CsRSecret *r_priv, | 96 | GNUNET_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 | */ | ||
149 | void | 104 | void |
150 | GNUNET_CRYPTO_cs_blinding_secrets_derive (const struct | 105 | GNUNET_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 | */ | ||
281 | void | 229 | void |
282 | GNUNET_CRYPTO_cs_calc_blinded_c (const struct GNUNET_CRYPTO_CsBlindingSecret | 230 | GNUNET_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 | */ | ||
328 | unsigned int | 259 | unsigned int |
329 | GNUNET_CRYPTO_cs_sign_derive (const struct GNUNET_CRYPTO_CsPrivateKey *priv, | 260 | GNUNET_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 | */ | ||
375 | void | 298 | void |
376 | GNUNET_CRYPTO_cs_unblind (const struct | 299 | GNUNET_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 | */ | ||
397 | enum GNUNET_GenericReturnValue | 310 | enum GNUNET_GenericReturnValue |
398 | GNUNET_CRYPTO_cs_verify (const struct GNUNET_CRYPTO_CsSignature *sig, | 311 | GNUNET_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; |