diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | auth2-jpake.c | 5 | ||||
-rw-r--r-- | jpake.c | 181 | ||||
-rw-r--r-- | jpake.h | 38 | ||||
-rw-r--r-- | monitor_wrap.c | 9 | ||||
-rw-r--r-- | monitor_wrap.h | 10 | ||||
-rw-r--r-- | schnorr.c | 374 | ||||
-rw-r--r-- | sshconnect2.c | 3 |
8 files changed, 351 insertions, 277 deletions
@@ -1,3 +1,11 @@ | |||
1 | 20090306 | ||
2 | - (djm) OpenBSD CVS Sync | ||
3 | - djm@cvs.openbsd.org 2009/03/05 07:18:19 | ||
4 | [auth2-jpake.c jpake.c jpake.h monitor_wrap.c monitor_wrap.h schnorr.c] | ||
5 | [sshconnect2.c] | ||
6 | refactor the (disabled) Schnorr proof code to make it a little more | ||
7 | generally useful | ||
8 | |||
1 | 20090223 | 9 | 20090223 |
2 | - (djm) OpenBSD CVS Sync | 10 | - (djm) OpenBSD CVS Sync |
3 | - djm@cvs.openbsd.org 2009/02/22 23:50:57 | 11 | - djm@cvs.openbsd.org 2009/02/22 23:50:57 |
diff --git a/auth2-jpake.c b/auth2-jpake.c index efe7ff2a3..6092e31c0 100644 --- a/auth2-jpake.c +++ b/auth2-jpake.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth2-jpake.c,v 1.2 2008/11/07 23:34:48 dtucker Exp $ */ | 1 | /* $OpenBSD: auth2-jpake.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 | * |
@@ -55,6 +55,7 @@ | |||
55 | #endif | 55 | #endif |
56 | #include "monitor_wrap.h" | 56 | #include "monitor_wrap.h" |
57 | 57 | ||
58 | #include "schnorr.h" | ||
58 | #include "jpake.h" | 59 | #include "jpake.h" |
59 | 60 | ||
60 | /* | 61 | /* |
@@ -359,7 +360,7 @@ auth2_jpake_get_pwdata(Authctxt *authctxt, BIGNUM **s, | |||
359 | } | 360 | } |
360 | 361 | ||
361 | /* | 362 | /* |
362 | * Being authentication attempt. | 363 | * Begin authentication attempt. |
363 | * Note, sets authctxt->postponed while in subprotocol | 364 | * Note, sets authctxt->postponed while in subprotocol |
364 | */ | 365 | */ |
365 | static int | 366 | static int |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: jpake.c,v 1.1 2008/11/04 08:22:12 djm Exp $ */ | 1 | /* $OpenBSD: jpake.c,v 1.2 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 | * |
@@ -47,6 +47,7 @@ | |||
47 | #include "log.h" | 47 | #include "log.h" |
48 | 48 | ||
49 | #include "jpake.h" | 49 | #include "jpake.h" |
50 | #include "schnorr.h" | ||
50 | 51 | ||
51 | #ifdef JPAKE | 52 | #ifdef JPAKE |
52 | 53 | ||
@@ -60,165 +61,10 @@ | |||
60 | "98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB" \ | 61 | "98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB" \ |
61 | "9ED529077096966D670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF" | 62 | "9ED529077096966D670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF" |
62 | 63 | ||
63 | struct jpake_group * | 64 | struct modp_group * |
64 | jpake_default_group(void) | 65 | jpake_default_group(void) |
65 | { | 66 | { |
66 | struct jpake_group *ret; | 67 | return modp_group_from_g_and_safe_p(JPAKE_GROUP_G, JPAKE_GROUP_P); |
67 | |||
68 | ret = xmalloc(sizeof(*ret)); | ||
69 | ret->p = ret->q = ret->g = NULL; | ||
70 | if (BN_hex2bn(&ret->p, JPAKE_GROUP_P) == 0 || | ||
71 | BN_hex2bn(&ret->g, JPAKE_GROUP_G) == 0) | ||
72 | fatal("%s: BN_hex2bn", __func__); | ||
73 | /* Subgroup order is p/2 (p is a safe prime) */ | ||
74 | if ((ret->q = BN_new()) == NULL) | ||
75 | fatal("%s: BN_new", __func__); | ||
76 | if (BN_rshift1(ret->q, ret->p) != 1) | ||
77 | fatal("%s: BN_rshift1", __func__); | ||
78 | |||
79 | return ret; | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * Generate uniformly distributed random number in range (1, high). | ||
84 | * Return number on success, NULL on failure. | ||
85 | */ | ||
86 | BIGNUM * | ||
87 | bn_rand_range_gt_one(const BIGNUM *high) | ||
88 | { | ||
89 | BIGNUM *r, *tmp; | ||
90 | int success = -1; | ||
91 | |||
92 | if ((tmp = BN_new()) == NULL) { | ||
93 | error("%s: BN_new", __func__); | ||
94 | return NULL; | ||
95 | } | ||
96 | if ((r = BN_new()) == NULL) { | ||
97 | error("%s: BN_new failed", __func__); | ||
98 | goto out; | ||
99 | } | ||
100 | if (BN_set_word(tmp, 2) != 1) { | ||
101 | error("%s: BN_set_word(tmp, 2)", __func__); | ||
102 | goto out; | ||
103 | } | ||
104 | if (BN_sub(tmp, high, tmp) == -1) { | ||
105 | error("%s: BN_sub failed (tmp = high - 2)", __func__); | ||
106 | goto out; | ||
107 | } | ||
108 | if (BN_rand_range(r, tmp) == -1) { | ||
109 | error("%s: BN_rand_range failed", __func__); | ||
110 | goto out; | ||
111 | } | ||
112 | if (BN_set_word(tmp, 2) != 1) { | ||
113 | error("%s: BN_set_word(tmp, 2)", __func__); | ||
114 | goto out; | ||
115 | } | ||
116 | if (BN_add(r, r, tmp) == -1) { | ||
117 | error("%s: BN_add failed (r = r + 2)", __func__); | ||
118 | goto out; | ||
119 | } | ||
120 | success = 0; | ||
121 | out: | ||
122 | BN_clear_free(tmp); | ||
123 | if (success == 0) | ||
124 | return r; | ||
125 | BN_clear_free(r); | ||
126 | return NULL; | ||
127 | } | ||
128 | |||
129 | /* | ||
130 | * Hash contents of buffer 'b' with hash 'md'. Returns 0 on success, | ||
131 | * with digest via 'digestp' (caller to free) and length via 'lenp'. | ||
132 | * Returns -1 on failure. | ||
133 | */ | ||
134 | int | ||
135 | hash_buffer(const u_char *buf, u_int len, const EVP_MD *md, | ||
136 | u_char **digestp, u_int *lenp) | ||
137 | { | ||
138 | u_char digest[EVP_MAX_MD_SIZE]; | ||
139 | u_int digest_len; | ||
140 | EVP_MD_CTX evp_md_ctx; | ||
141 | int success = -1; | ||
142 | |||
143 | EVP_MD_CTX_init(&evp_md_ctx); | ||
144 | |||
145 | if (EVP_DigestInit_ex(&evp_md_ctx, md, NULL) != 1) { | ||
146 | error("%s: EVP_DigestInit_ex", __func__); | ||
147 | goto out; | ||
148 | } | ||
149 | if (EVP_DigestUpdate(&evp_md_ctx, buf, len) != 1) { | ||
150 | error("%s: EVP_DigestUpdate", __func__); | ||
151 | goto out; | ||
152 | } | ||
153 | if (EVP_DigestFinal_ex(&evp_md_ctx, digest, &digest_len) != 1) { | ||
154 | error("%s: EVP_DigestFinal_ex", __func__); | ||
155 | goto out; | ||
156 | } | ||
157 | *digestp = xmalloc(digest_len); | ||
158 | *lenp = digest_len; | ||
159 | memcpy(*digestp, digest, *lenp); | ||
160 | success = 0; | ||
161 | out: | ||
162 | EVP_MD_CTX_cleanup(&evp_md_ctx); | ||
163 | bzero(digest, sizeof(digest)); | ||
164 | digest_len = 0; | ||
165 | return success; | ||
166 | } | ||
167 | |||
168 | /* print formatted string followed by bignum */ | ||
169 | void | ||
170 | jpake_debug3_bn(const BIGNUM *n, const char *fmt, ...) | ||
171 | { | ||
172 | char *out, *h; | ||
173 | va_list args; | ||
174 | |||
175 | out = NULL; | ||
176 | va_start(args, fmt); | ||
177 | vasprintf(&out, fmt, args); | ||
178 | va_end(args); | ||
179 | if (out == NULL) | ||
180 | fatal("%s: vasprintf failed", __func__); | ||
181 | |||
182 | if (n == NULL) | ||
183 | debug3("%s(null)", out); | ||
184 | else { | ||
185 | h = BN_bn2hex(n); | ||
186 | debug3("%s0x%s", out, h); | ||
187 | free(h); | ||
188 | } | ||
189 | free(out); | ||
190 | } | ||
191 | |||
192 | /* print formatted string followed by buffer contents in hex */ | ||
193 | void | ||
194 | jpake_debug3_buf(const u_char *buf, u_int len, const char *fmt, ...) | ||
195 | { | ||
196 | char *out, h[65]; | ||
197 | u_int i, j; | ||
198 | va_list args; | ||
199 | |||
200 | out = NULL; | ||
201 | va_start(args, fmt); | ||
202 | vasprintf(&out, fmt, args); | ||
203 | va_end(args); | ||
204 | if (out == NULL) | ||
205 | fatal("%s: vasprintf failed", __func__); | ||
206 | |||
207 | debug3("%s length %u%s", out, len, buf == NULL ? " (null)" : ""); | ||
208 | free(out); | ||
209 | if (buf == NULL) | ||
210 | return; | ||
211 | |||
212 | *h = '\0'; | ||
213 | for (i = j = 0; i < len; i++) { | ||
214 | snprintf(h + j, sizeof(h) - j, "%02x", buf[i]); | ||
215 | j += 2; | ||
216 | if (j >= sizeof(h) - 1 || i == len - 1) { | ||
217 | debug3(" %s", h); | ||
218 | *h = '\0'; | ||
219 | j = 0; | ||
220 | } | ||
221 | } | ||
222 | } | 68 | } |
223 | 69 | ||
224 | struct jpake_ctx * | 70 | struct jpake_ctx * |
@@ -243,7 +89,6 @@ jpake_new(void) | |||
243 | return ret; | 89 | return ret; |
244 | } | 90 | } |
245 | 91 | ||
246 | |||
247 | void | 92 | void |
248 | jpake_free(struct jpake_ctx *pctx) | 93 | jpake_free(struct jpake_ctx *pctx) |
249 | { | 94 | { |
@@ -344,7 +189,7 @@ jpake_dump(struct jpake_ctx *pctx, const char *fmt, ...) | |||
344 | 189 | ||
345 | /* Shared parts of step 1 exchange calculation */ | 190 | /* Shared parts of step 1 exchange calculation */ |
346 | void | 191 | void |
347 | jpake_step1(struct jpake_group *grp, | 192 | jpake_step1(struct modp_group *grp, |
348 | u_char **id, u_int *id_len, | 193 | u_char **id, u_int *id_len, |
349 | BIGNUM **priv1, BIGNUM **priv2, BIGNUM **g_priv1, BIGNUM **g_priv2, | 194 | BIGNUM **priv1, BIGNUM **priv2, BIGNUM **g_priv1, BIGNUM **g_priv2, |
350 | u_char **priv1_proof, u_int *priv1_proof_len, | 195 | u_char **priv1_proof, u_int *priv1_proof_len, |
@@ -383,11 +228,11 @@ jpake_step1(struct jpake_group *grp, | |||
383 | fatal("%s: BN_mod_exp", __func__); | 228 | fatal("%s: BN_mod_exp", __func__); |
384 | 229 | ||
385 | /* Generate proofs for holding x1/x3 and x2/x4 */ | 230 | /* Generate proofs for holding x1/x3 and x2/x4 */ |
386 | if (schnorr_sign(grp->p, grp->q, grp->g, | 231 | if (schnorr_sign_buf(grp->p, grp->q, grp->g, |
387 | *priv1, *g_priv1, *id, *id_len, | 232 | *priv1, *g_priv1, *id, *id_len, |
388 | priv1_proof, priv1_proof_len) != 0) | 233 | priv1_proof, priv1_proof_len) != 0) |
389 | fatal("%s: schnorr_sign", __func__); | 234 | fatal("%s: schnorr_sign", __func__); |
390 | if (schnorr_sign(grp->p, grp->q, grp->g, | 235 | if (schnorr_sign_buf(grp->p, grp->q, grp->g, |
391 | *priv2, *g_priv2, *id, *id_len, | 236 | *priv2, *g_priv2, *id, *id_len, |
392 | priv2_proof, priv2_proof_len) != 0) | 237 | priv2_proof, priv2_proof_len) != 0) |
393 | fatal("%s: schnorr_sign", __func__); | 238 | fatal("%s: schnorr_sign", __func__); |
@@ -397,7 +242,7 @@ jpake_step1(struct jpake_group *grp, | |||
397 | 242 | ||
398 | /* Shared parts of step 2 exchange calculation */ | 243 | /* Shared parts of step 2 exchange calculation */ |
399 | void | 244 | void |
400 | jpake_step2(struct jpake_group *grp, BIGNUM *s, | 245 | jpake_step2(struct modp_group *grp, BIGNUM *s, |
401 | BIGNUM *mypub1, BIGNUM *theirpub1, BIGNUM *theirpub2, BIGNUM *mypriv2, | 246 | BIGNUM *mypub1, BIGNUM *theirpub1, BIGNUM *theirpub2, BIGNUM *mypriv2, |
402 | const u_char *theirid, u_int theirid_len, | 247 | const u_char *theirid, u_int theirid_len, |
403 | const u_char *myid, u_int myid_len, | 248 | const u_char *myid, u_int myid_len, |
@@ -415,10 +260,10 @@ jpake_step2(struct jpake_group *grp, BIGNUM *s, | |||
415 | if (BN_cmp(theirpub2, BN_value_one()) <= 0) | 260 | if (BN_cmp(theirpub2, BN_value_one()) <= 0) |
416 | fatal("%s: theirpub2 <= 1", __func__); | 261 | fatal("%s: theirpub2 <= 1", __func__); |
417 | 262 | ||
418 | if (schnorr_verify(grp->p, grp->q, grp->g, theirpub1, | 263 | if (schnorr_verify_buf(grp->p, grp->q, grp->g, theirpub1, |
419 | theirid, theirid_len, theirpub1_proof, theirpub1_proof_len) != 1) | 264 | theirid, theirid_len, theirpub1_proof, theirpub1_proof_len) != 1) |
420 | fatal("%s: schnorr_verify theirpub1 failed", __func__); | 265 | fatal("%s: schnorr_verify theirpub1 failed", __func__); |
421 | if (schnorr_verify(grp->p, grp->q, grp->g, theirpub2, | 266 | if (schnorr_verify_buf(grp->p, grp->q, grp->g, theirpub2, |
422 | theirid, theirid_len, theirpub2_proof, theirpub2_proof_len) != 1) | 267 | theirid, theirid_len, theirpub2_proof, theirpub2_proof_len) != 1) |
423 | fatal("%s: schnorr_verify theirpub2 failed", __func__); | 268 | fatal("%s: schnorr_verify theirpub2 failed", __func__); |
424 | 269 | ||
@@ -459,7 +304,7 @@ jpake_step2(struct jpake_group *grp, BIGNUM *s, | |||
459 | JPAKE_DEBUG_BN((exponent, "%s: exponent = ", __func__)); | 304 | JPAKE_DEBUG_BN((exponent, "%s: exponent = ", __func__)); |
460 | 305 | ||
461 | /* Note the generator here is 'tmp', not g */ | 306 | /* Note the generator here is 'tmp', not g */ |
462 | if (schnorr_sign(grp->p, grp->q, tmp, exponent, *newpub, | 307 | if (schnorr_sign_buf(grp->p, grp->q, tmp, exponent, *newpub, |
463 | myid, myid_len, | 308 | myid, myid_len, |
464 | newpub_exponent_proof, newpub_exponent_proof_len) != 0) | 309 | newpub_exponent_proof, newpub_exponent_proof_len) != 0) |
465 | fatal("%s: schnorr_sign newpub", __func__); | 310 | fatal("%s: schnorr_sign newpub", __func__); |
@@ -496,7 +341,7 @@ jpake_confirm_hash(const BIGNUM *k, | |||
496 | 341 | ||
497 | /* Shared parts of key derivation and confirmation calculation */ | 342 | /* Shared parts of key derivation and confirmation calculation */ |
498 | void | 343 | void |
499 | jpake_key_confirm(struct jpake_group *grp, BIGNUM *s, BIGNUM *step2_val, | 344 | jpake_key_confirm(struct modp_group *grp, BIGNUM *s, BIGNUM *step2_val, |
500 | BIGNUM *mypriv2, BIGNUM *mypub1, BIGNUM *mypub2, | 345 | BIGNUM *mypriv2, BIGNUM *mypub1, BIGNUM *mypub2, |
501 | BIGNUM *theirpub1, BIGNUM *theirpub2, | 346 | BIGNUM *theirpub1, BIGNUM *theirpub2, |
502 | const u_char *my_id, u_int my_id_len, | 347 | const u_char *my_id, u_int my_id_len, |
@@ -531,7 +376,7 @@ jpake_key_confirm(struct jpake_group *grp, BIGNUM *s, BIGNUM *step2_val, | |||
531 | 376 | ||
532 | JPAKE_DEBUG_BN((tmp, "%s: tmp = ", __func__)); | 377 | JPAKE_DEBUG_BN((tmp, "%s: tmp = ", __func__)); |
533 | 378 | ||
534 | if (schnorr_verify(grp->p, grp->q, tmp, step2_val, | 379 | if (schnorr_verify_buf(grp->p, grp->q, tmp, step2_val, |
535 | their_id, their_id_len, | 380 | their_id, their_id_len, |
536 | theirpriv2_s_proof, theirpriv2_s_proof_len) != 1) | 381 | theirpriv2_s_proof, theirpriv2_s_proof_len) != 1) |
537 | fatal("%s: schnorr_verify theirpriv2_s_proof failed", __func__); | 382 | fatal("%s: schnorr_verify theirpriv2_s_proof failed", __func__); |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: jpake.h,v 1.1 2008/11/04 08:22:13 djm Exp $ */ | 1 | /* $OpenBSD: jpake.h,v 1.2 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 | * |
@@ -28,20 +28,16 @@ | |||
28 | # define JPAKE_DEBUG_BUF(a) | 28 | # define JPAKE_DEBUG_BUF(a) |
29 | # define JPAKE_DEBUG_CTX(a) | 29 | # define JPAKE_DEBUG_CTX(a) |
30 | #else | 30 | #else |
31 | # define JPAKE_DEBUG_BN(a) jpake_debug3_bn a | 31 | # define JPAKE_DEBUG_BN(a) debug3_bn a |
32 | # define JPAKE_DEBUG_BUF(a) jpake_debug3_buf a | 32 | # define JPAKE_DEBUG_BUF(a) debug3_buf a |
33 | # define JPAKE_DEBUG_CTX(a) jpake_dump a | 33 | # define JPAKE_DEBUG_CTX(a) jpake_dump a |
34 | #endif /* SCHNORR_DEBUG */ | 34 | #endif /* JPAKE_DEBUG */ |
35 | |||
36 | struct jpake_group { | ||
37 | BIGNUM *p, *q, *g; | ||
38 | }; | ||
39 | 35 | ||
40 | #define KZP_ID_LEN 16 /* Length of client and server IDs */ | 36 | #define KZP_ID_LEN 16 /* Length of client and server IDs */ |
41 | 37 | ||
42 | struct jpake_ctx { | 38 | struct jpake_ctx { |
43 | /* Parameters */ | 39 | /* Parameters */ |
44 | struct jpake_group *grp; | 40 | struct modp_group *grp; |
45 | 41 | ||
46 | /* Private values shared by client and server */ | 42 | /* Private values shared by client and server */ |
47 | BIGNUM *s; /* Secret (salted, crypted password) */ | 43 | BIGNUM *s; /* Secret (salted, crypted password) */ |
@@ -83,26 +79,18 @@ struct jpake_ctx { | |||
83 | }; | 79 | }; |
84 | 80 | ||
85 | /* jpake.c */ | 81 | /* jpake.c */ |
86 | struct jpake_group *jpake_default_group(void); | 82 | struct modp_group *jpake_default_group(void); |
87 | BIGNUM *bn_rand_range_gt_one(const BIGNUM *high); | ||
88 | int hash_buffer(const u_char *, u_int, const EVP_MD *, u_char **, u_int *); | ||
89 | void jpake_debug3_bn(const BIGNUM *, const char *, ...) | ||
90 | __attribute__((__nonnull__ (2))) | ||
91 | __attribute__((format(printf, 2, 3))); | ||
92 | void jpake_debug3_buf(const u_char *, u_int, const char *, ...) | ||
93 | __attribute__((__nonnull__ (3))) | ||
94 | __attribute__((format(printf, 3, 4))); | ||
95 | void jpake_dump(struct jpake_ctx *, const char *, ...) | 83 | void jpake_dump(struct jpake_ctx *, const char *, ...) |
96 | __attribute__((__nonnull__ (2))) | 84 | __attribute__((__nonnull__ (2))) |
97 | __attribute__((format(printf, 2, 3))); | 85 | __attribute__((format(printf, 2, 3))); |
98 | struct jpake_ctx *jpake_new(void); | 86 | struct jpake_ctx *jpake_new(void); |
99 | void jpake_free(struct jpake_ctx *); | 87 | void jpake_free(struct jpake_ctx *); |
100 | 88 | ||
101 | void jpake_step1(struct jpake_group *, u_char **, u_int *, | 89 | void jpake_step1(struct modp_group *, u_char **, u_int *, |
102 | BIGNUM **, BIGNUM **, BIGNUM **, BIGNUM **, | 90 | BIGNUM **, BIGNUM **, BIGNUM **, BIGNUM **, |
103 | u_char **, u_int *, u_char **, u_int *); | 91 | u_char **, u_int *, u_char **, u_int *); |
104 | 92 | ||
105 | void jpake_step2(struct jpake_group *, BIGNUM *, | 93 | void jpake_step2(struct modp_group *, BIGNUM *, |
106 | BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, | 94 | BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, |
107 | const u_char *, u_int, const u_char *, u_int, | 95 | const u_char *, u_int, const u_char *, u_int, |
108 | const u_char *, u_int, const u_char *, u_int, | 96 | const u_char *, u_int, const u_char *, u_int, |
@@ -113,7 +101,7 @@ void jpake_confirm_hash(const BIGNUM *, | |||
113 | const u_char *, u_int, | 101 | const u_char *, u_int, |
114 | u_char **, u_int *); | 102 | u_char **, u_int *); |
115 | 103 | ||
116 | void jpake_key_confirm(struct jpake_group *, BIGNUM *, BIGNUM *, | 104 | void jpake_key_confirm(struct modp_group *, BIGNUM *, BIGNUM *, |
117 | BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, | 105 | BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, |
118 | const u_char *, u_int, const u_char *, u_int, | 106 | const u_char *, u_int, const u_char *, u_int, |
119 | const u_char *, u_int, const u_char *, u_int, | 107 | const u_char *, u_int, const u_char *, u_int, |
@@ -122,13 +110,5 @@ void jpake_key_confirm(struct jpake_group *, BIGNUM *, BIGNUM *, | |||
122 | int jpake_check_confirm(const BIGNUM *, const u_char *, u_int, | 110 | int jpake_check_confirm(const BIGNUM *, const u_char *, u_int, |
123 | const u_char *, u_int, const u_char *, u_int); | 111 | const u_char *, u_int, const u_char *, u_int); |
124 | 112 | ||
125 | /* schnorr.c */ | ||
126 | int schnorr_sign(const BIGNUM *, const BIGNUM *, const BIGNUM *, | ||
127 | const BIGNUM *, const BIGNUM *, const u_char *, u_int , | ||
128 | u_char **, u_int *); | ||
129 | int schnorr_verify(const BIGNUM *, const BIGNUM *, const BIGNUM *, | ||
130 | const BIGNUM *, const u_char *, u_int, | ||
131 | const u_char *, u_int); | ||
132 | |||
133 | #endif /* JPAKE_H */ | 113 | #endif /* JPAKE_H */ |
134 | 114 | ||
diff --git a/monitor_wrap.c b/monitor_wrap.c index 0986fc518..db3251b93 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: monitor_wrap.c,v 1.64 2008/11/04 08:22:13 djm Exp $ */ | 1 | /* $OpenBSD: monitor_wrap.c,v 1.65 2009/03/05 07:18:19 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> | 3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> |
4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> | 4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> |
@@ -71,6 +71,7 @@ | |||
71 | #include "atomicio.h" | 71 | #include "atomicio.h" |
72 | #include "monitor_fdpass.h" | 72 | #include "monitor_fdpass.h" |
73 | #include "misc.h" | 73 | #include "misc.h" |
74 | #include "schnorr.h" | ||
74 | #include "jpake.h" | 75 | #include "jpake.h" |
75 | 76 | ||
76 | #include "channels.h" | 77 | #include "channels.h" |
@@ -1282,7 +1283,7 @@ mm_auth2_jpake_get_pwdata(Authctxt *authctxt, BIGNUM **s, | |||
1282 | } | 1283 | } |
1283 | 1284 | ||
1284 | void | 1285 | void |
1285 | mm_jpake_step1(struct jpake_group *grp, | 1286 | mm_jpake_step1(struct modp_group *grp, |
1286 | u_char **id, u_int *id_len, | 1287 | u_char **id, u_int *id_len, |
1287 | BIGNUM **priv1, BIGNUM **priv2, BIGNUM **g_priv1, BIGNUM **g_priv2, | 1288 | BIGNUM **priv1, BIGNUM **priv2, BIGNUM **g_priv1, BIGNUM **g_priv2, |
1288 | u_char **priv1_proof, u_int *priv1_proof_len, | 1289 | u_char **priv1_proof, u_int *priv1_proof_len, |
@@ -1317,7 +1318,7 @@ mm_jpake_step1(struct jpake_group *grp, | |||
1317 | } | 1318 | } |
1318 | 1319 | ||
1319 | void | 1320 | void |
1320 | mm_jpake_step2(struct jpake_group *grp, BIGNUM *s, | 1321 | mm_jpake_step2(struct modp_group *grp, BIGNUM *s, |
1321 | BIGNUM *mypub1, BIGNUM *theirpub1, BIGNUM *theirpub2, BIGNUM *mypriv2, | 1322 | BIGNUM *mypub1, BIGNUM *theirpub1, BIGNUM *theirpub2, BIGNUM *mypriv2, |
1322 | const u_char *theirid, u_int theirid_len, | 1323 | const u_char *theirid, u_int theirid_len, |
1323 | const u_char *myid, u_int myid_len, | 1324 | const u_char *myid, u_int myid_len, |
@@ -1357,7 +1358,7 @@ mm_jpake_step2(struct jpake_group *grp, BIGNUM *s, | |||
1357 | } | 1358 | } |
1358 | 1359 | ||
1359 | void | 1360 | void |
1360 | mm_jpake_key_confirm(struct jpake_group *grp, BIGNUM *s, BIGNUM *step2_val, | 1361 | mm_jpake_key_confirm(struct modp_group *grp, BIGNUM *s, BIGNUM *step2_val, |
1361 | BIGNUM *mypriv2, BIGNUM *mypub1, BIGNUM *mypub2, | 1362 | BIGNUM *mypriv2, BIGNUM *mypub1, BIGNUM *mypub2, |
1362 | BIGNUM *theirpub1, BIGNUM *theirpub2, | 1363 | BIGNUM *theirpub1, BIGNUM *theirpub2, |
1363 | const u_char *my_id, u_int my_id_len, | 1364 | const u_char *my_id, u_int my_id_len, |
diff --git a/monitor_wrap.h b/monitor_wrap.h index 55c4b99f3..de2d16f66 100644 --- a/monitor_wrap.h +++ b/monitor_wrap.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: monitor_wrap.h,v 1.21 2008/11/04 08:22:13 djm Exp $ */ | 1 | /* $OpenBSD: monitor_wrap.h,v 1.22 2009/03/05 07:18:19 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> | 4 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> |
@@ -102,17 +102,17 @@ int mm_skey_query(void *, char **, char **, u_int *, char ***, u_int **); | |||
102 | int mm_skey_respond(void *, u_int, char **); | 102 | int mm_skey_respond(void *, u_int, char **); |
103 | 103 | ||
104 | /* jpake */ | 104 | /* jpake */ |
105 | struct jpake_group; | 105 | struct modp_group; |
106 | void mm_auth2_jpake_get_pwdata(struct Authctxt *, BIGNUM **, char **, char **); | 106 | void mm_auth2_jpake_get_pwdata(struct Authctxt *, BIGNUM **, char **, char **); |
107 | void mm_jpake_step1(struct jpake_group *, u_char **, u_int *, | 107 | void mm_jpake_step1(struct modp_group *, u_char **, u_int *, |
108 | BIGNUM **, BIGNUM **, BIGNUM **, BIGNUM **, | 108 | BIGNUM **, BIGNUM **, BIGNUM **, BIGNUM **, |
109 | u_char **, u_int *, u_char **, u_int *); | 109 | u_char **, u_int *, u_char **, u_int *); |
110 | void mm_jpake_step2(struct jpake_group *, BIGNUM *, | 110 | void mm_jpake_step2(struct modp_group *, BIGNUM *, |
111 | BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, | 111 | BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, |
112 | const u_char *, u_int, const u_char *, u_int, | 112 | const u_char *, u_int, const u_char *, u_int, |
113 | const u_char *, u_int, const u_char *, u_int, | 113 | const u_char *, u_int, const u_char *, u_int, |
114 | BIGNUM **, u_char **, u_int *); | 114 | BIGNUM **, u_char **, u_int *); |
115 | void mm_jpake_key_confirm(struct jpake_group *, BIGNUM *, BIGNUM *, | 115 | void mm_jpake_key_confirm(struct modp_group *, BIGNUM *, BIGNUM *, |
116 | BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, | 116 | BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, |
117 | const u_char *, u_int, const u_char *, u_int, | 117 | const u_char *, u_int, const u_char *, u_int, |
118 | const u_char *, u_int, const u_char *, u_int, | 118 | const u_char *, u_int, const u_char *, u_int, |
@@ -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 | ||
diff --git a/sshconnect2.c b/sshconnect2.c index a762eec3b..260c6307a 100644 --- a/sshconnect2.c +++ b/sshconnect2.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshconnect2.c,v 1.170 2008/11/04 08:22:13 djm Exp $ */ | 1 | /* $OpenBSD: sshconnect2.c,v 1.171 2009/03/05 07:18:19 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2008 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2008 Damien Miller. All rights reserved. |
@@ -68,6 +68,7 @@ | |||
68 | #include "msg.h" | 68 | #include "msg.h" |
69 | #include "pathnames.h" | 69 | #include "pathnames.h" |
70 | #include "uidswap.h" | 70 | #include "uidswap.h" |
71 | #include "schnorr.h" | ||
71 | #include "jpake.h" | 72 | #include "jpake.h" |
72 | 73 | ||
73 | #ifdef GSSAPI | 74 | #ifdef GSSAPI |