diff options
author | Damien Miller <djm@mindrot.org> | 2014-01-10 10:58:53 +1100 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2014-01-10 10:58:53 +1100 |
commit | b3051d01e505c9c2dc00faab472a0d06fa6b0e65 (patch) | |
tree | c0ca49b5fc4e5e1a066157b4dbd9c68cfcd41d63 /schnorr.c | |
parent | e00e413dd16eb747fb2c15a099971d91c13cf70f (diff) |
- djm@cvs.openbsd.org 2014/01/09 23:20:00
[digest.c digest.h hostfile.c kex.c kex.h kexc25519.c kexc25519c.c]
[kexc25519s.c kexdh.c kexecdh.c kexecdhc.c kexecdhs.c kexgex.c kexgexc.c]
[kexgexs.c key.c key.h roaming_client.c roaming_common.c schnorr.c]
[schnorr.h ssh-dss.c ssh-ecdsa.c ssh-rsa.c sshconnect2.c]
Introduce digest API and use it to perform all hashing operations
rather than calling OpenSSL EVP_Digest* directly. Will make it easier
to build a reduced-feature OpenSSH without OpenSSL in future;
feedback, ok markus@
Diffstat (limited to 'schnorr.c')
-rw-r--r-- | schnorr.c | 57 |
1 files changed, 24 insertions, 33 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: schnorr.c,v 1.8 2013/11/08 00:39:15 djm Exp $ */ | 1 | /* $OpenBSD: schnorr.c,v 1.9 2014/01/09 23:20:00 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2008 Damien Miller. All rights reserved. | 3 | * Copyright (c) 2008 Damien Miller. All rights reserved. |
4 | * | 4 | * |
@@ -41,6 +41,7 @@ | |||
41 | #include "log.h" | 41 | #include "log.h" |
42 | 42 | ||
43 | #include "schnorr.h" | 43 | #include "schnorr.h" |
44 | #include "digest.h" | ||
44 | 45 | ||
45 | #include "openbsd-compat/openssl-compat.h" | 46 | #include "openbsd-compat/openssl-compat.h" |
46 | 47 | ||
@@ -57,12 +58,12 @@ | |||
57 | 58 | ||
58 | /* | 59 | /* |
59 | * Calculate hash component of Schnorr signature H(g || g^v || g^x || id) | 60 | * Calculate hash component of Schnorr signature H(g || g^v || g^x || id) |
60 | * using the hash function defined by "evp_md". Returns signature as | 61 | * using the hash function defined by "hash_alg". Returns signature as |
61 | * bignum or NULL on error. | 62 | * bignum or NULL on error. |
62 | */ | 63 | */ |
63 | static BIGNUM * | 64 | static BIGNUM * |
64 | schnorr_hash(const BIGNUM *p, const BIGNUM *q, const BIGNUM *g, | 65 | schnorr_hash(const BIGNUM *p, const BIGNUM *q, const BIGNUM *g, |
65 | const EVP_MD *evp_md, const BIGNUM *g_v, const BIGNUM *g_x, | 66 | int hash_alg, const BIGNUM *g_v, const BIGNUM *g_x, |
66 | const u_char *id, u_int idlen) | 67 | const u_char *id, u_int idlen) |
67 | { | 68 | { |
68 | u_char *digest; | 69 | u_char *digest; |
@@ -88,7 +89,7 @@ schnorr_hash(const BIGNUM *p, const BIGNUM *q, const BIGNUM *g, | |||
88 | 89 | ||
89 | SCHNORR_DEBUG_BUF((buffer_ptr(&b), buffer_len(&b), | 90 | SCHNORR_DEBUG_BUF((buffer_ptr(&b), buffer_len(&b), |
90 | "%s: hashblob", __func__)); | 91 | "%s: hashblob", __func__)); |
91 | if (hash_buffer(buffer_ptr(&b), buffer_len(&b), evp_md, | 92 | if (hash_buffer(buffer_ptr(&b), buffer_len(&b), hash_alg, |
92 | &digest, &digest_len) != 0) { | 93 | &digest, &digest_len) != 0) { |
93 | error("%s: hash_buffer", __func__); | 94 | error("%s: hash_buffer", __func__); |
94 | goto out; | 95 | goto out; |
@@ -113,7 +114,7 @@ schnorr_hash(const BIGNUM *p, const BIGNUM *q, const BIGNUM *g, | |||
113 | /* | 114 | /* |
114 | * Generate Schnorr signature to prove knowledge of private value 'x' used | 115 | * Generate Schnorr signature to prove knowledge of private value 'x' used |
115 | * in public exponent g^x, under group defined by 'grp_p', 'grp_q' and 'grp_g' | 116 | * in public exponent g^x, under group defined by 'grp_p', 'grp_q' and 'grp_g' |
116 | * using the hash function "evp_md". | 117 | * using the hash function "hash_alg". |
117 | * 'idlen' bytes from 'id' will be included in the signature hash as an anti- | 118 | * 'idlen' bytes from 'id' will be included in the signature hash as an anti- |
118 | * replay salt. | 119 | * replay salt. |
119 | * | 120 | * |
@@ -123,7 +124,7 @@ schnorr_hash(const BIGNUM *p, const BIGNUM *q, const BIGNUM *g, | |||
123 | */ | 124 | */ |
124 | int | 125 | int |
125 | schnorr_sign(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, | 126 | schnorr_sign(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, |
126 | const EVP_MD *evp_md, const BIGNUM *x, const BIGNUM *g_x, | 127 | int hash_alg, const BIGNUM *x, const BIGNUM *g_x, |
127 | const u_char *id, u_int idlen, BIGNUM **r_p, BIGNUM **e_p) | 128 | const u_char *id, u_int idlen, BIGNUM **r_p, BIGNUM **e_p) |
128 | { | 129 | { |
129 | int success = -1; | 130 | int success = -1; |
@@ -173,7 +174,7 @@ schnorr_sign(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, | |||
173 | SCHNORR_DEBUG_BN((g_v, "%s: g_v = ", __func__)); | 174 | SCHNORR_DEBUG_BN((g_v, "%s: g_v = ", __func__)); |
174 | 175 | ||
175 | /* h = H(g || g^v || g^x || id) */ | 176 | /* h = H(g || g^v || g^x || id) */ |
176 | if ((h = schnorr_hash(grp_p, grp_q, grp_g, evp_md, g_v, g_x, | 177 | if ((h = schnorr_hash(grp_p, grp_q, grp_g, hash_alg, g_v, g_x, |
177 | id, idlen)) == NULL) { | 178 | id, idlen)) == NULL) { |
178 | error("%s: schnorr_hash failed", __func__); | 179 | error("%s: schnorr_hash failed", __func__); |
179 | goto out; | 180 | goto out; |
@@ -223,7 +224,7 @@ schnorr_sign_buf(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, | |||
223 | Buffer b; | 224 | Buffer b; |
224 | BIGNUM *r, *e; | 225 | BIGNUM *r, *e; |
225 | 226 | ||
226 | if (schnorr_sign(grp_p, grp_q, grp_g, EVP_sha256(), | 227 | if (schnorr_sign(grp_p, grp_q, grp_g, SSH_DIGEST_SHA256, |
227 | x, g_x, id, idlen, &r, &e) != 0) | 228 | x, g_x, id, idlen, &r, &e) != 0) |
228 | return -1; | 229 | return -1; |
229 | 230 | ||
@@ -248,13 +249,13 @@ schnorr_sign_buf(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, | |||
248 | /* | 249 | /* |
249 | * Verify Schnorr signature { r (v - xh mod q), e (g^v mod p) } against | 250 | * Verify Schnorr signature { r (v - xh mod q), e (g^v mod p) } against |
250 | * public exponent g_x (g^x) under group defined by 'grp_p', 'grp_q' and | 251 | * public exponent g_x (g^x) under group defined by 'grp_p', 'grp_q' and |
251 | * 'grp_g' using hash "evp_md". | 252 | * 'grp_g' using hash "hash_alg". |
252 | * Signature hash will be salted with 'idlen' bytes from 'id'. | 253 | * Signature hash will be salted with 'idlen' bytes from 'id'. |
253 | * Returns -1 on failure, 0 on incorrect signature or 1 on matching signature. | 254 | * Returns -1 on failure, 0 on incorrect signature or 1 on matching signature. |
254 | */ | 255 | */ |
255 | int | 256 | int |
256 | schnorr_verify(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, | 257 | schnorr_verify(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, |
257 | const EVP_MD *evp_md, const BIGNUM *g_x, const u_char *id, u_int idlen, | 258 | int hash_alg, const BIGNUM *g_x, const u_char *id, u_int idlen, |
258 | const BIGNUM *r, const BIGNUM *e) | 259 | const BIGNUM *r, const BIGNUM *e) |
259 | { | 260 | { |
260 | int success = -1; | 261 | int success = -1; |
@@ -302,7 +303,7 @@ schnorr_verify(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, | |||
302 | 303 | ||
303 | SCHNORR_DEBUG_BN((g_xh, "%s: g_xh = ", __func__)); | 304 | SCHNORR_DEBUG_BN((g_xh, "%s: g_xh = ", __func__)); |
304 | /* h = H(g || g^v || g^x || id) */ | 305 | /* h = H(g || g^v || g^x || id) */ |
305 | if ((h = schnorr_hash(grp_p, grp_q, grp_g, evp_md, e, g_x, | 306 | if ((h = schnorr_hash(grp_p, grp_q, grp_g, hash_alg, e, g_x, |
306 | id, idlen)) == NULL) { | 307 | id, idlen)) == NULL) { |
307 | error("%s: schnorr_hash failed", __func__); | 308 | error("%s: schnorr_hash failed", __func__); |
308 | goto out; | 309 | goto out; |
@@ -385,7 +386,7 @@ schnorr_verify_buf(const BIGNUM *grp_p, const BIGNUM *grp_q, | |||
385 | goto out; | 386 | goto out; |
386 | } | 387 | } |
387 | 388 | ||
388 | ret = schnorr_verify(grp_p, grp_q, grp_g, EVP_sha256(), | 389 | ret = schnorr_verify(grp_p, grp_q, grp_g, SSH_DIGEST_SHA256, |
389 | g_x, id, idlen, r, e); | 390 | g_x, id, idlen, r, e); |
390 | out: | 391 | out: |
391 | BN_clear_free(e); | 392 | BN_clear_free(e); |
@@ -443,43 +444,33 @@ bn_rand_range_gt_one(const BIGNUM *high) | |||
443 | return NULL; | 444 | return NULL; |
444 | } | 445 | } |
445 | 446 | ||
447 | /* XXX convert all callers of this to use ssh_digest_memory() directly */ | ||
446 | /* | 448 | /* |
447 | * Hash contents of buffer 'b' with hash 'md'. Returns 0 on success, | 449 | * Hash contents of buffer 'b' with hash 'md'. Returns 0 on success, |
448 | * with digest via 'digestp' (caller to free) and length via 'lenp'. | 450 | * with digest via 'digestp' (caller to free) and length via 'lenp'. |
449 | * Returns -1 on failure. | 451 | * Returns -1 on failure. |
450 | */ | 452 | */ |
451 | int | 453 | int |
452 | hash_buffer(const u_char *buf, u_int len, const EVP_MD *md, | 454 | hash_buffer(const u_char *buf, u_int len, int hash_alg, |
453 | u_char **digestp, u_int *lenp) | 455 | u_char **digestp, u_int *lenp) |
454 | { | 456 | { |
455 | u_char digest[EVP_MAX_MD_SIZE]; | 457 | u_char digest[SSH_DIGEST_MAX_LENGTH]; |
456 | u_int digest_len; | 458 | u_int digest_len = ssh_digest_bytes(hash_alg); |
457 | EVP_MD_CTX evp_md_ctx; | ||
458 | int success = -1; | ||
459 | 459 | ||
460 | EVP_MD_CTX_init(&evp_md_ctx); | 460 | if (digest_len == 0) { |
461 | 461 | error("%s: invalid hash", __func__); | |
462 | if (EVP_DigestInit_ex(&evp_md_ctx, md, NULL) != 1) { | 462 | return -1; |
463 | error("%s: EVP_DigestInit_ex", __func__); | ||
464 | goto out; | ||
465 | } | ||
466 | if (EVP_DigestUpdate(&evp_md_ctx, buf, len) != 1) { | ||
467 | error("%s: EVP_DigestUpdate", __func__); | ||
468 | goto out; | ||
469 | } | 463 | } |
470 | if (EVP_DigestFinal_ex(&evp_md_ctx, digest, &digest_len) != 1) { | 464 | if (ssh_digest_memory(hash_alg, buf, len, digest, digest_len) != 0) { |
471 | error("%s: EVP_DigestFinal_ex", __func__); | 465 | error("%s: digest_memory failed", __func__); |
472 | goto out; | 466 | return -1; |
473 | } | 467 | } |
474 | *digestp = xmalloc(digest_len); | 468 | *digestp = xmalloc(digest_len); |
475 | *lenp = digest_len; | 469 | *lenp = digest_len; |
476 | memcpy(*digestp, digest, *lenp); | 470 | memcpy(*digestp, digest, *lenp); |
477 | success = 0; | ||
478 | out: | ||
479 | EVP_MD_CTX_cleanup(&evp_md_ctx); | ||
480 | bzero(digest, sizeof(digest)); | 471 | bzero(digest, sizeof(digest)); |
481 | digest_len = 0; | 472 | digest_len = 0; |
482 | return success; | 473 | return 0; |
483 | } | 474 | } |
484 | 475 | ||
485 | /* print formatted string followed by bignum */ | 476 | /* print formatted string followed by bignum */ |