diff options
Diffstat (limited to 'schnorr.c')
-rw-r--r-- | schnorr.c | 374 |
1 files changed, 306 insertions, 68 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: schnorr.c,v 1.2 2009/02/18 04:31:21 djm Exp $ */ | 1 | /* $OpenBSD: schnorr.c,v 1.3 2009/03/05 07:18:19 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2008 Damien Miller. All rights reserved. | 3 | * Copyright (c) 2008 Damien Miller. All rights reserved. |
4 | * | 4 | * |
@@ -40,36 +40,32 @@ | |||
40 | #include "buffer.h" | 40 | #include "buffer.h" |
41 | #include "log.h" | 41 | #include "log.h" |
42 | 42 | ||
43 | #include "jpake.h" | 43 | #include "schnorr.h" |
44 | 44 | ||
45 | /* #define SCHNORR_DEBUG */ /* Privacy-violating debugging */ | 45 | /* #define SCHNORR_DEBUG */ /* Privacy-violating debugging */ |
46 | /* #define SCHNORR_MAIN */ /* Include main() selftest */ | 46 | /* #define SCHNORR_MAIN */ /* Include main() selftest */ |
47 | 47 | ||
48 | /* XXX */ | ||
49 | /* Parametise signature hash? (sha256, sha1, etc.) */ | ||
50 | /* Signature format - include type name, hash type, group params? */ | ||
51 | |||
52 | #ifndef SCHNORR_DEBUG | 48 | #ifndef SCHNORR_DEBUG |
53 | # define SCHNORR_DEBUG_BN(a) | 49 | # define SCHNORR_DEBUG_BN(a) |
54 | # define SCHNORR_DEBUG_BUF(a) | 50 | # define SCHNORR_DEBUG_BUF(a) |
55 | #else | 51 | #else |
56 | # define SCHNORR_DEBUG_BN(a) jpake_debug3_bn a | 52 | # define SCHNORR_DEBUG_BN(a) debug3_bn a |
57 | # define SCHNORR_DEBUG_BUF(a) jpake_debug3_buf a | 53 | # define SCHNORR_DEBUG_BUF(a) debug3_buf a |
58 | #endif /* SCHNORR_DEBUG */ | 54 | #endif /* SCHNORR_DEBUG */ |
59 | 55 | ||
60 | /* | 56 | /* |
61 | * Calculate hash component of Schnorr signature H(g || g^v || g^x || id) | 57 | * Calculate hash component of Schnorr signature H(g || g^v || g^x || id) |
62 | * using SHA1. Returns signature as bignum or NULL on error. | 58 | * using the hash function defined by "evp_md". Returns signature as |
59 | * bignum or NULL on error. | ||
63 | */ | 60 | */ |
64 | static BIGNUM * | 61 | static BIGNUM * |
65 | schnorr_hash(const BIGNUM *p, const BIGNUM *q, const BIGNUM *g, | 62 | schnorr_hash(const BIGNUM *p, const BIGNUM *q, const BIGNUM *g, |
66 | const BIGNUM *g_v, const BIGNUM *g_x, | 63 | const EVP_MD *evp_md, const BIGNUM *g_v, const BIGNUM *g_x, |
67 | const u_char *id, u_int idlen) | 64 | const u_char *id, u_int idlen) |
68 | { | 65 | { |
69 | u_char *digest; | 66 | u_char *digest; |
70 | u_int digest_len; | 67 | u_int digest_len; |
71 | BIGNUM *h; | 68 | BIGNUM *h; |
72 | EVP_MD_CTX evp_md_ctx; | ||
73 | Buffer b; | 69 | Buffer b; |
74 | int success = -1; | 70 | int success = -1; |
75 | 71 | ||
@@ -79,7 +75,6 @@ schnorr_hash(const BIGNUM *p, const BIGNUM *q, const BIGNUM *g, | |||
79 | } | 75 | } |
80 | 76 | ||
81 | buffer_init(&b); | 77 | buffer_init(&b); |
82 | EVP_MD_CTX_init(&evp_md_ctx); | ||
83 | 78 | ||
84 | /* h = H(g || p || q || g^v || g^x || id) */ | 79 | /* h = H(g || p || q || g^v || g^x || id) */ |
85 | buffer_put_bignum2(&b, g); | 80 | buffer_put_bignum2(&b, g); |
@@ -91,7 +86,7 @@ schnorr_hash(const BIGNUM *p, const BIGNUM *q, const BIGNUM *g, | |||
91 | 86 | ||
92 | SCHNORR_DEBUG_BUF((buffer_ptr(&b), buffer_len(&b), | 87 | SCHNORR_DEBUG_BUF((buffer_ptr(&b), buffer_len(&b), |
93 | "%s: hashblob", __func__)); | 88 | "%s: hashblob", __func__)); |
94 | if (hash_buffer(buffer_ptr(&b), buffer_len(&b), EVP_sha256(), | 89 | if (hash_buffer(buffer_ptr(&b), buffer_len(&b), evp_md, |
95 | &digest, &digest_len) != 0) { | 90 | &digest, &digest_len) != 0) { |
96 | error("%s: hash_buffer", __func__); | 91 | error("%s: hash_buffer", __func__); |
97 | goto out; | 92 | goto out; |
@@ -104,7 +99,6 @@ schnorr_hash(const BIGNUM *p, const BIGNUM *q, const BIGNUM *g, | |||
104 | SCHNORR_DEBUG_BN((h, "%s: h = ", __func__)); | 99 | SCHNORR_DEBUG_BN((h, "%s: h = ", __func__)); |
105 | out: | 100 | out: |
106 | buffer_free(&b); | 101 | buffer_free(&b); |
107 | EVP_MD_CTX_cleanup(&evp_md_ctx); | ||
108 | bzero(digest, digest_len); | 102 | bzero(digest, digest_len); |
109 | xfree(digest); | 103 | xfree(digest); |
110 | digest_len = 0; | 104 | digest_len = 0; |
@@ -117,18 +111,20 @@ schnorr_hash(const BIGNUM *p, const BIGNUM *q, const BIGNUM *g, | |||
117 | /* | 111 | /* |
118 | * Generate Schnorr signature to prove knowledge of private value 'x' used | 112 | * Generate Schnorr signature to prove knowledge of private value 'x' used |
119 | * in public exponent g^x, under group defined by 'grp_p', 'grp_q' and 'grp_g' | 113 | * in public exponent g^x, under group defined by 'grp_p', 'grp_q' and 'grp_g' |
114 | * using the hash function "evp_md". | ||
120 | * 'idlen' bytes from 'id' will be included in the signature hash as an anti- | 115 | * 'idlen' bytes from 'id' will be included in the signature hash as an anti- |
121 | * replay salt. | 116 | * replay salt. |
122 | * On success, 0 is returned and *siglen bytes of signature are returned in | 117 | * |
123 | * *sig (caller to free). Returns -1 on failure. | 118 | * On success, 0 is returned. The signature values are returned as *e_p |
119 | * (g^v mod p) and *r_p (v - xh mod q). The caller must free these values. | ||
120 | * On failure, -1 is returned. | ||
124 | */ | 121 | */ |
125 | int | 122 | int |
126 | schnorr_sign(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, | 123 | schnorr_sign(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, |
127 | const BIGNUM *x, const BIGNUM *g_x, const u_char *id, u_int idlen, | 124 | const EVP_MD *evp_md, const BIGNUM *x, const BIGNUM *g_x, |
128 | u_char **sig, u_int *siglen) | 125 | const u_char *id, u_int idlen, BIGNUM **r_p, BIGNUM **e_p) |
129 | { | 126 | { |
130 | int success = -1; | 127 | int success = -1; |
131 | Buffer b; | ||
132 | BIGNUM *h, *tmp, *v, *g_v, *r; | 128 | BIGNUM *h, *tmp, *v, *g_v, *r; |
133 | BN_CTX *bn_ctx; | 129 | BN_CTX *bn_ctx; |
134 | 130 | ||
@@ -171,7 +167,7 @@ schnorr_sign(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, | |||
171 | SCHNORR_DEBUG_BN((g_v, "%s: g_v = ", __func__)); | 167 | SCHNORR_DEBUG_BN((g_v, "%s: g_v = ", __func__)); |
172 | 168 | ||
173 | /* h = H(g || g^v || g^x || id) */ | 169 | /* h = H(g || g^v || g^x || id) */ |
174 | if ((h = schnorr_hash(grp_p, grp_q, grp_g, g_v, g_x, | 170 | if ((h = schnorr_hash(grp_p, grp_q, grp_g, evp_md, g_v, g_x, |
175 | id, idlen)) == NULL) { | 171 | id, idlen)) == NULL) { |
176 | error("%s: schnorr_hash failed", __func__); | 172 | error("%s: schnorr_hash failed", __func__); |
177 | goto out; | 173 | goto out; |
@@ -186,12 +182,49 @@ schnorr_sign(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, | |||
186 | error("%s: BN_mod_mul (r = v - tmp)", __func__); | 182 | error("%s: BN_mod_mul (r = v - tmp)", __func__); |
187 | goto out; | 183 | goto out; |
188 | } | 184 | } |
185 | SCHNORR_DEBUG_BN((g_v, "%s: e = ", __func__)); | ||
189 | SCHNORR_DEBUG_BN((r, "%s: r = ", __func__)); | 186 | SCHNORR_DEBUG_BN((r, "%s: r = ", __func__)); |
190 | 187 | ||
191 | /* Signature is (g_v, r) */ | 188 | *e_p = g_v; |
189 | *r_p = r; | ||
190 | |||
191 | success = 0; | ||
192 | out: | ||
193 | BN_CTX_free(bn_ctx); | ||
194 | if (h != NULL) | ||
195 | BN_clear_free(h); | ||
196 | if (v != NULL) | ||
197 | BN_clear_free(v); | ||
198 | BN_clear_free(tmp); | ||
199 | |||
200 | return success; | ||
201 | } | ||
202 | |||
203 | /* | ||
204 | * Generate Schnorr signature to prove knowledge of private value 'x' used | ||
205 | * in public exponent g^x, under group defined by 'grp_p', 'grp_q' and 'grp_g' | ||
206 | * using a SHA256 hash. | ||
207 | * 'idlen' bytes from 'id' will be included in the signature hash as an anti- | ||
208 | * replay salt. | ||
209 | * On success, 0 is returned and *siglen bytes of signature are returned in | ||
210 | * *sig (caller to free). Returns -1 on failure. | ||
211 | */ | ||
212 | int | ||
213 | schnorr_sign_buf(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, | ||
214 | const BIGNUM *x, const BIGNUM *g_x, const u_char *id, u_int idlen, | ||
215 | u_char **sig, u_int *siglen) | ||
216 | { | ||
217 | Buffer b; | ||
218 | BIGNUM *r, *e; | ||
219 | |||
220 | if (schnorr_sign(grp_p, grp_q, grp_g, EVP_sha256(), | ||
221 | x, g_x, id, idlen, &r, &e) != 0) | ||
222 | return -1; | ||
223 | |||
224 | /* Signature is (e, r) */ | ||
192 | buffer_init(&b); | 225 | buffer_init(&b); |
193 | /* XXX sigtype-hash as string? */ | 226 | /* XXX sigtype-hash as string? */ |
194 | buffer_put_bignum2(&b, g_v); | 227 | buffer_put_bignum2(&b, e); |
195 | buffer_put_bignum2(&b, r); | 228 | buffer_put_bignum2(&b, r); |
196 | *siglen = buffer_len(&b); | 229 | *siglen = buffer_len(&b); |
197 | *sig = xmalloc(*siglen); | 230 | *sig = xmalloc(*siglen); |
@@ -199,36 +232,28 @@ schnorr_sign(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, | |||
199 | SCHNORR_DEBUG_BUF((buffer_ptr(&b), buffer_len(&b), | 232 | SCHNORR_DEBUG_BUF((buffer_ptr(&b), buffer_len(&b), |
200 | "%s: sigblob", __func__)); | 233 | "%s: sigblob", __func__)); |
201 | buffer_free(&b); | 234 | buffer_free(&b); |
202 | success = 0; | 235 | |
203 | out: | ||
204 | BN_CTX_free(bn_ctx); | ||
205 | if (h != NULL) | ||
206 | BN_clear_free(h); | ||
207 | if (v != NULL) | ||
208 | BN_clear_free(v); | ||
209 | BN_clear_free(r); | 236 | BN_clear_free(r); |
210 | BN_clear_free(g_v); | 237 | BN_clear_free(e); |
211 | BN_clear_free(tmp); | ||
212 | 238 | ||
213 | return success; | 239 | return 0; |
214 | } | 240 | } |
215 | 241 | ||
216 | /* | 242 | /* |
217 | * Verify Schnorr signature 'sig' of length 'siglen' against public exponent | 243 | * Verify Schnorr signature { r (v - xh mod q), e (g^v mod p) } against |
218 | * g_x (g^x) under group defined by 'grp_p', 'grp_q' and 'grp_g'. | 244 | * public exponent g_x (g^x) under group defined by 'grp_p', 'grp_q' and |
245 | * 'grp_g' using hash "evp_md". | ||
219 | * Signature hash will be salted with 'idlen' bytes from 'id'. | 246 | * Signature hash will be salted with 'idlen' bytes from 'id'. |
220 | * Returns -1 on failure, 0 on incorrect signature or 1 on matching signature. | 247 | * Returns -1 on failure, 0 on incorrect signature or 1 on matching signature. |
221 | */ | 248 | */ |
222 | int | 249 | int |
223 | schnorr_verify(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, | 250 | schnorr_verify(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, |
224 | const BIGNUM *g_x, const u_char *id, u_int idlen, | 251 | const EVP_MD *evp_md, const BIGNUM *g_x, const u_char *id, u_int idlen, |
225 | const u_char *sig, u_int siglen) | 252 | const BIGNUM *r, const BIGNUM *e) |
226 | { | 253 | { |
227 | int success = -1; | 254 | int success = -1; |
228 | Buffer b; | 255 | BIGNUM *h, *g_xh, *g_r, *expected; |
229 | BIGNUM *g_v, *h, *r, *g_xh, *g_r, *expected; | ||
230 | BN_CTX *bn_ctx; | 256 | BN_CTX *bn_ctx; |
231 | u_int rlen; | ||
232 | 257 | ||
233 | SCHNORR_DEBUG_BN((g_x, "%s: g_x = ", __func__)); | 258 | SCHNORR_DEBUG_BN((g_x, "%s: g_x = ", __func__)); |
234 | 259 | ||
@@ -238,39 +263,23 @@ schnorr_verify(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, | |||
238 | return -1; | 263 | return -1; |
239 | } | 264 | } |
240 | 265 | ||
241 | g_v = h = r = g_xh = g_r = expected = NULL; | 266 | h = g_xh = g_r = expected = NULL; |
242 | if ((bn_ctx = BN_CTX_new()) == NULL) { | 267 | if ((bn_ctx = BN_CTX_new()) == NULL) { |
243 | error("%s: BN_CTX_new", __func__); | 268 | error("%s: BN_CTX_new", __func__); |
244 | goto out; | 269 | goto out; |
245 | } | 270 | } |
246 | if ((g_v = BN_new()) == NULL || | 271 | if ((g_xh = BN_new()) == NULL || |
247 | (r = BN_new()) == NULL || | ||
248 | (g_xh = BN_new()) == NULL || | ||
249 | (g_r = BN_new()) == NULL || | 272 | (g_r = BN_new()) == NULL || |
250 | (expected = BN_new()) == NULL) { | 273 | (expected = BN_new()) == NULL) { |
251 | error("%s: BN_new", __func__); | 274 | error("%s: BN_new", __func__); |
252 | goto out; | 275 | goto out; |
253 | } | 276 | } |
254 | 277 | ||
255 | /* Extract g^v and r from signature blob */ | 278 | SCHNORR_DEBUG_BN((e, "%s: e = ", __func__)); |
256 | buffer_init(&b); | ||
257 | buffer_append(&b, sig, siglen); | ||
258 | SCHNORR_DEBUG_BUF((buffer_ptr(&b), buffer_len(&b), | ||
259 | "%s: sigblob", __func__)); | ||
260 | buffer_get_bignum2(&b, g_v); | ||
261 | buffer_get_bignum2(&b, r); | ||
262 | rlen = buffer_len(&b); | ||
263 | buffer_free(&b); | ||
264 | if (rlen != 0) { | ||
265 | error("%s: remaining bytes in signature %d", __func__, rlen); | ||
266 | goto out; | ||
267 | } | ||
268 | buffer_free(&b); | ||
269 | SCHNORR_DEBUG_BN((g_v, "%s: g_v = ", __func__)); | ||
270 | SCHNORR_DEBUG_BN((r, "%s: r = ", __func__)); | 279 | SCHNORR_DEBUG_BN((r, "%s: r = ", __func__)); |
271 | 280 | ||
272 | /* h = H(g || g^v || g^x || id) */ | 281 | /* h = H(g || g^v || g^x || id) */ |
273 | if ((h = schnorr_hash(grp_p, grp_q, grp_g, g_v, g_x, | 282 | if ((h = schnorr_hash(grp_p, grp_q, grp_g, evp_md, e, g_x, |
274 | id, idlen)) == NULL) { | 283 | id, idlen)) == NULL) { |
275 | error("%s: schnorr_hash failed", __func__); | 284 | error("%s: schnorr_hash failed", __func__); |
276 | goto out; | 285 | goto out; |
@@ -297,20 +306,248 @@ schnorr_verify(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, | |||
297 | } | 306 | } |
298 | SCHNORR_DEBUG_BN((expected, "%s: expected = ", __func__)); | 307 | SCHNORR_DEBUG_BN((expected, "%s: expected = ", __func__)); |
299 | 308 | ||
300 | /* Check g_v == expected */ | 309 | /* Check e == expected */ |
301 | success = BN_cmp(expected, g_v) == 0; | 310 | success = BN_cmp(expected, e) == 0; |
302 | out: | 311 | out: |
303 | BN_CTX_free(bn_ctx); | 312 | BN_CTX_free(bn_ctx); |
304 | if (h != NULL) | 313 | if (h != NULL) |
305 | BN_clear_free(h); | 314 | BN_clear_free(h); |
306 | BN_clear_free(g_v); | ||
307 | BN_clear_free(r); | ||
308 | BN_clear_free(g_xh); | 315 | BN_clear_free(g_xh); |
309 | BN_clear_free(g_r); | 316 | BN_clear_free(g_r); |
310 | BN_clear_free(expected); | 317 | BN_clear_free(expected); |
311 | return success; | 318 | return success; |
312 | } | 319 | } |
313 | 320 | ||
321 | /* | ||
322 | * Verify Schnorr signature 'sig' of length 'siglen' against public exponent | ||
323 | * g_x (g^x) under group defined by 'grp_p', 'grp_q' and 'grp_g' using a | ||
324 | * SHA256 hash. | ||
325 | * Signature hash will be salted with 'idlen' bytes from 'id'. | ||
326 | * Returns -1 on failure, 0 on incorrect signature or 1 on matching signature. | ||
327 | */ | ||
328 | int | ||
329 | schnorr_verify_buf(const BIGNUM *grp_p, const BIGNUM *grp_q, | ||
330 | const BIGNUM *grp_g, | ||
331 | const BIGNUM *g_x, const u_char *id, u_int idlen, | ||
332 | const u_char *sig, u_int siglen) | ||
333 | { | ||
334 | Buffer b; | ||
335 | int ret = -1; | ||
336 | u_int rlen; | ||
337 | BIGNUM *r, *e; | ||
338 | |||
339 | e = r = NULL; | ||
340 | if ((e = BN_new()) == NULL || | ||
341 | (r = BN_new()) == NULL) { | ||
342 | error("%s: BN_new", __func__); | ||
343 | goto out; | ||
344 | } | ||
345 | |||
346 | /* Extract g^v and r from signature blob */ | ||
347 | buffer_init(&b); | ||
348 | buffer_append(&b, sig, siglen); | ||
349 | SCHNORR_DEBUG_BUF((buffer_ptr(&b), buffer_len(&b), | ||
350 | "%s: sigblob", __func__)); | ||
351 | buffer_get_bignum2(&b, e); | ||
352 | buffer_get_bignum2(&b, r); | ||
353 | rlen = buffer_len(&b); | ||
354 | buffer_free(&b); | ||
355 | if (rlen != 0) { | ||
356 | error("%s: remaining bytes in signature %d", __func__, rlen); | ||
357 | goto out; | ||
358 | } | ||
359 | |||
360 | ret = schnorr_verify(grp_p, grp_q, grp_g, EVP_sha256(), | ||
361 | g_x, id, idlen, r, e); | ||
362 | out: | ||
363 | BN_clear_free(e); | ||
364 | BN_clear_free(r); | ||
365 | |||
366 | return ret; | ||
367 | } | ||
368 | |||
369 | /* Helper functions */ | ||
370 | |||
371 | /* | ||
372 | * Generate uniformly distributed random number in range (1, high). | ||
373 | * Return number on success, NULL on failure. | ||
374 | */ | ||
375 | BIGNUM * | ||
376 | bn_rand_range_gt_one(const BIGNUM *high) | ||
377 | { | ||
378 | BIGNUM *r, *tmp; | ||
379 | int success = -1; | ||
380 | |||
381 | if ((tmp = BN_new()) == NULL) { | ||
382 | error("%s: BN_new", __func__); | ||
383 | return NULL; | ||
384 | } | ||
385 | if ((r = BN_new()) == NULL) { | ||
386 | error("%s: BN_new failed", __func__); | ||
387 | goto out; | ||
388 | } | ||
389 | if (BN_set_word(tmp, 2) != 1) { | ||
390 | error("%s: BN_set_word(tmp, 2)", __func__); | ||
391 | goto out; | ||
392 | } | ||
393 | if (BN_sub(tmp, high, tmp) == -1) { | ||
394 | error("%s: BN_sub failed (tmp = high - 2)", __func__); | ||
395 | goto out; | ||
396 | } | ||
397 | if (BN_rand_range(r, tmp) == -1) { | ||
398 | error("%s: BN_rand_range failed", __func__); | ||
399 | goto out; | ||
400 | } | ||
401 | if (BN_set_word(tmp, 2) != 1) { | ||
402 | error("%s: BN_set_word(tmp, 2)", __func__); | ||
403 | goto out; | ||
404 | } | ||
405 | if (BN_add(r, r, tmp) == -1) { | ||
406 | error("%s: BN_add failed (r = r + 2)", __func__); | ||
407 | goto out; | ||
408 | } | ||
409 | success = 0; | ||
410 | out: | ||
411 | BN_clear_free(tmp); | ||
412 | if (success == 0) | ||
413 | return r; | ||
414 | BN_clear_free(r); | ||
415 | return NULL; | ||
416 | } | ||
417 | |||
418 | /* | ||
419 | * Hash contents of buffer 'b' with hash 'md'. Returns 0 on success, | ||
420 | * with digest via 'digestp' (caller to free) and length via 'lenp'. | ||
421 | * Returns -1 on failure. | ||
422 | */ | ||
423 | int | ||
424 | hash_buffer(const u_char *buf, u_int len, const EVP_MD *md, | ||
425 | u_char **digestp, u_int *lenp) | ||
426 | { | ||
427 | u_char digest[EVP_MAX_MD_SIZE]; | ||
428 | u_int digest_len; | ||
429 | EVP_MD_CTX evp_md_ctx; | ||
430 | int success = -1; | ||
431 | |||
432 | EVP_MD_CTX_init(&evp_md_ctx); | ||
433 | |||
434 | if (EVP_DigestInit_ex(&evp_md_ctx, md, NULL) != 1) { | ||
435 | error("%s: EVP_DigestInit_ex", __func__); | ||
436 | goto out; | ||
437 | } | ||
438 | if (EVP_DigestUpdate(&evp_md_ctx, buf, len) != 1) { | ||
439 | error("%s: EVP_DigestUpdate", __func__); | ||
440 | goto out; | ||
441 | } | ||
442 | if (EVP_DigestFinal_ex(&evp_md_ctx, digest, &digest_len) != 1) { | ||
443 | error("%s: EVP_DigestFinal_ex", __func__); | ||
444 | goto out; | ||
445 | } | ||
446 | *digestp = xmalloc(digest_len); | ||
447 | *lenp = digest_len; | ||
448 | memcpy(*digestp, digest, *lenp); | ||
449 | success = 0; | ||
450 | out: | ||
451 | EVP_MD_CTX_cleanup(&evp_md_ctx); | ||
452 | bzero(digest, sizeof(digest)); | ||
453 | digest_len = 0; | ||
454 | return success; | ||
455 | } | ||
456 | |||
457 | /* print formatted string followed by bignum */ | ||
458 | void | ||
459 | debug3_bn(const BIGNUM *n, const char *fmt, ...) | ||
460 | { | ||
461 | char *out, *h; | ||
462 | va_list args; | ||
463 | |||
464 | out = NULL; | ||
465 | va_start(args, fmt); | ||
466 | vasprintf(&out, fmt, args); | ||
467 | va_end(args); | ||
468 | if (out == NULL) | ||
469 | fatal("%s: vasprintf failed", __func__); | ||
470 | |||
471 | if (n == NULL) | ||
472 | debug3("%s(null)", out); | ||
473 | else { | ||
474 | h = BN_bn2hex(n); | ||
475 | debug3("%s0x%s", out, h); | ||
476 | free(h); | ||
477 | } | ||
478 | free(out); | ||
479 | } | ||
480 | |||
481 | /* print formatted string followed by buffer contents in hex */ | ||
482 | void | ||
483 | debug3_buf(const u_char *buf, u_int len, const char *fmt, ...) | ||
484 | { | ||
485 | char *out, h[65]; | ||
486 | u_int i, j; | ||
487 | va_list args; | ||
488 | |||
489 | out = NULL; | ||
490 | va_start(args, fmt); | ||
491 | vasprintf(&out, fmt, args); | ||
492 | va_end(args); | ||
493 | if (out == NULL) | ||
494 | fatal("%s: vasprintf failed", __func__); | ||
495 | |||
496 | debug3("%s length %u%s", out, len, buf == NULL ? " (null)" : ""); | ||
497 | free(out); | ||
498 | if (buf == NULL) | ||
499 | return; | ||
500 | |||
501 | *h = '\0'; | ||
502 | for (i = j = 0; i < len; i++) { | ||
503 | snprintf(h + j, sizeof(h) - j, "%02x", buf[i]); | ||
504 | j += 2; | ||
505 | if (j >= sizeof(h) - 1 || i == len - 1) { | ||
506 | debug3(" %s", h); | ||
507 | *h = '\0'; | ||
508 | j = 0; | ||
509 | } | ||
510 | } | ||
511 | } | ||
512 | |||
513 | /* | ||
514 | * Construct a MODP group from hex strings p (which must be a safe | ||
515 | * prime) and g, automatically calculating subgroup q as (p / 2) | ||
516 | */ | ||
517 | struct modp_group * | ||
518 | modp_group_from_g_and_safe_p(const char *grp_g, const char *grp_p) | ||
519 | { | ||
520 | struct modp_group *ret; | ||
521 | |||
522 | ret = xmalloc(sizeof(*ret)); | ||
523 | ret->p = ret->q = ret->g = NULL; | ||
524 | if (BN_hex2bn(&ret->p, grp_p) == 0 || | ||
525 | BN_hex2bn(&ret->g, grp_g) == 0) | ||
526 | fatal("%s: BN_hex2bn", __func__); | ||
527 | /* Subgroup order is p/2 (p is a safe prime) */ | ||
528 | if ((ret->q = BN_new()) == NULL) | ||
529 | fatal("%s: BN_new", __func__); | ||
530 | if (BN_rshift1(ret->q, ret->p) != 1) | ||
531 | fatal("%s: BN_rshift1", __func__); | ||
532 | |||
533 | return ret; | ||
534 | } | ||
535 | |||
536 | void | ||
537 | modp_group_free(struct modp_group *grp) | ||
538 | { | ||
539 | if (grp->g != NULL) | ||
540 | BN_clear_free(grp->g); | ||
541 | if (grp->p != NULL) | ||
542 | BN_clear_free(grp->p); | ||
543 | if (grp->q != NULL) | ||
544 | BN_clear_free(grp->q); | ||
545 | bzero(grp, sizeof(*grp)); | ||
546 | xfree(grp); | ||
547 | } | ||
548 | |||
549 | /* main() function for self-test */ | ||
550 | |||
314 | #ifdef SCHNORR_MAIN | 551 | #ifdef SCHNORR_MAIN |
315 | static void | 552 | static void |
316 | schnorr_selftest_one(const BIGNUM *grp_p, const BIGNUM *grp_q, | 553 | schnorr_selftest_one(const BIGNUM *grp_p, const BIGNUM *grp_q, |
@@ -328,16 +565,17 @@ schnorr_selftest_one(const BIGNUM *grp_p, const BIGNUM *grp_q, | |||
328 | 565 | ||
329 | if (BN_mod_exp(g_x, grp_g, x, grp_p, bn_ctx) == -1) | 566 | if (BN_mod_exp(g_x, grp_g, x, grp_p, bn_ctx) == -1) |
330 | fatal("%s: g_x", __func__); | 567 | fatal("%s: g_x", __func__); |
331 | if (schnorr_sign(grp_p, grp_q, grp_g, x, g_x, "junk", 4, &sig, &siglen)) | 568 | if (schnorr_sign_buf(grp_p, grp_q, grp_g, x, g_x, "junk", 4, |
569 | &sig, &siglen)) | ||
332 | fatal("%s: schnorr_sign", __func__); | 570 | fatal("%s: schnorr_sign", __func__); |
333 | if (schnorr_verify(grp_p, grp_q, grp_g, g_x, "junk", 4, | 571 | if (schnorr_verify_buf(grp_p, grp_q, grp_g, g_x, "junk", 4, |
334 | sig, siglen) != 1) | 572 | sig, siglen) != 1) |
335 | fatal("%s: verify fail", __func__); | 573 | fatal("%s: verify fail", __func__); |
336 | if (schnorr_verify(grp_p, grp_q, grp_g, g_x, "JUNK", 4, | 574 | if (schnorr_verify_buf(grp_p, grp_q, grp_g, g_x, "JUNK", 4, |
337 | sig, siglen) != 0) | 575 | sig, siglen) != 0) |
338 | fatal("%s: verify should have failed (bad ID)", __func__); | 576 | fatal("%s: verify should have failed (bad ID)", __func__); |
339 | sig[4] ^= 1; | 577 | sig[4] ^= 1; |
340 | if (schnorr_verify(grp_p, grp_q, grp_g, g_x, "junk", 4, | 578 | if (schnorr_verify_buf(grp_p, grp_q, grp_g, g_x, "junk", 4, |
341 | sig, siglen) != 0) | 579 | sig, siglen) != 0) |
342 | fatal("%s: verify should have failed (bit error)", __func__); | 580 | fatal("%s: verify should have failed (bit error)", __func__); |
343 | xfree(sig); | 581 | xfree(sig); |
@@ -349,7 +587,7 @@ static void | |||
349 | schnorr_selftest(void) | 587 | schnorr_selftest(void) |
350 | { | 588 | { |
351 | BIGNUM *x; | 589 | BIGNUM *x; |
352 | struct jpake_group *grp; | 590 | struct modp_group *grp; |
353 | u_int i; | 591 | u_int i; |
354 | char *hh; | 592 | char *hh; |
355 | 593 | ||