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