summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2014-02-04 11:02:42 +1100
committerDamien Miller <djm@mindrot.org>2014-02-04 11:02:42 +1100
commit4e8d937af79ce4e253f77ec93489d098b25becc3 (patch)
tree83b0293313eea8dfebcc7f906c5058f530238e8b
parent69d0d09f76bab5aec86fbf78489169f63bd16475 (diff)
- markus@cvs.openbsd.org 2014/01/27 18:58:14
[Makefile.in digest.c digest.h hostfile.c kex.h mac.c hmac.c hmac.h] replace openssl HMAC with an implementation based on our ssh_digest_* ok and feedback djm@
-rw-r--r--ChangeLog7
-rw-r--r--Makefile.in4
-rw-r--r--digest.c25
-rw-r--r--digest.h12
-rw-r--r--hmac.c197
-rw-r--r--hmac.h37
-rw-r--r--hostfile.c29
-rw-r--r--kex.h7
-rw-r--r--mac.c85
9 files changed, 332 insertions, 71 deletions
diff --git a/ChangeLog b/ChangeLog
index 46f157df8..8b619de7d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
120140204
2 - OpenBSD CVS Sync
3 - markus@cvs.openbsd.org 2014/01/27 18:58:14
4 [Makefile.in digest.c digest.h hostfile.c kex.h mac.c hmac.c hmac.h]
5 replace openssl HMAC with an implementation based on our ssh_digest_*
6 ok and feedback djm@
7
120140131 820140131
2 - (djm) [sandbox-seccomp-filter.c sandbox-systrace.c] Allow shutdown(2) 9 - (djm) [sandbox-seccomp-filter.c sandbox-systrace.c] Allow shutdown(2)
3 syscall from sandboxes; it may be called by packet_close. 10 syscall from sandboxes; it may be called by packet_close.
diff --git a/Makefile.in b/Makefile.in
index 41f704bb4..99ac27ebb 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,4 +1,4 @@
1# $Id: Makefile.in,v 1.353 2014/01/31 22:25:19 tim Exp $ 1# $Id: Makefile.in,v 1.354 2014/02/04 00:02:43 djm Exp $
2 2
3# uncomment if you run a non bourne compatable shell. Ie. csh 3# uncomment if you run a non bourne compatable shell. Ie. csh
4#SHELL = @SH@ 4#SHELL = @SH@
@@ -75,7 +75,7 @@ LIBSSH_OBJS=authfd.o authfile.o bufaux.o bufbn.o buffer.o \
75 msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ 75 msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \
76 jpake.o schnorr.o ssh-pkcs11.o krl.o smult_curve25519_ref.o \ 76 jpake.o schnorr.o ssh-pkcs11.o krl.o smult_curve25519_ref.o \
77 kexc25519.o kexc25519c.o poly1305.o chacha.o cipher-chachapoly.o \ 77 kexc25519.o kexc25519c.o poly1305.o chacha.o cipher-chachapoly.o \
78 ssh-ed25519.o digest.o \ 78 ssh-ed25519.o digest.o hmac.o \
79 sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o blocks.o 79 sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o blocks.o
80 80
81SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ 81SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
diff --git a/digest.c b/digest.c
index a221819eb..1a11b2b1c 100644
--- a/digest.c
+++ b/digest.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: digest.c,v 1.3 2014/01/20 00:08:48 djm Exp $ */ 1/* $OpenBSD: digest.c,v 1.4 2014/01/27 18:58:14 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2013 Damien Miller <djm@mindrot.org> 3 * Copyright (c) 2013 Damien Miller <djm@mindrot.org>
4 * 4 *
@@ -72,6 +72,12 @@ ssh_digest_bytes(int alg)
72 return digest == NULL ? 0 : digest->digest_len; 72 return digest == NULL ? 0 : digest->digest_len;
73} 73}
74 74
75size_t
76ssh_digest_blocksize(struct ssh_digest_ctx *ctx)
77{
78 return EVP_MD_CTX_block_size(&ctx->mdctx);
79}
80
75struct ssh_digest_ctx * 81struct ssh_digest_ctx *
76ssh_digest_start(int alg) 82ssh_digest_start(int alg)
77{ 83{
@@ -90,6 +96,15 @@ ssh_digest_start(int alg)
90} 96}
91 97
92int 98int
99ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to)
100{
101 /* we have bcopy-style order while openssl has memcpy-style */
102 if (!EVP_MD_CTX_copy_ex(&to->mdctx, &from->mdctx))
103 return -1;
104 return 0;
105}
106
107int
93ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen) 108ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen)
94{ 109{
95 if (EVP_DigestUpdate(&ctx->mdctx, m, mlen) != 1) 110 if (EVP_DigestUpdate(&ctx->mdctx, m, mlen) != 1)
@@ -123,9 +138,11 @@ ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen)
123void 138void
124ssh_digest_free(struct ssh_digest_ctx *ctx) 139ssh_digest_free(struct ssh_digest_ctx *ctx)
125{ 140{
126 EVP_MD_CTX_cleanup(&ctx->mdctx); 141 if (ctx != NULL) {
127 memset(ctx, 0, sizeof(*ctx)); 142 EVP_MD_CTX_cleanup(&ctx->mdctx);
128 free(ctx); 143 memset(ctx, 0, sizeof(*ctx));
144 free(ctx);
145 }
129} 146}
130 147
131int 148int
diff --git a/digest.h b/digest.h
index faefda3f5..0fb207fca 100644
--- a/digest.h
+++ b/digest.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: digest.h,v 1.1 2014/01/09 23:20:00 djm Exp $ */ 1/* $OpenBSD: digest.h,v 1.2 2014/01/27 18:58:14 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2013 Damien Miller <djm@mindrot.org> 3 * Copyright (c) 2013 Damien Miller <djm@mindrot.org>
4 * 4 *
@@ -30,9 +30,18 @@
30#define SSH_DIGEST_SHA512 5 30#define SSH_DIGEST_SHA512 5
31#define SSH_DIGEST_MAX 6 31#define SSH_DIGEST_MAX 6
32 32
33struct ssh_digest_ctx;
34
33/* Returns the algorithm's digest length in bytes or 0 for invalid algorithm */ 35/* Returns the algorithm's digest length in bytes or 0 for invalid algorithm */
34size_t ssh_digest_bytes(int alg); 36size_t ssh_digest_bytes(int alg);
35 37
38/* Returns the block size of the digest, e.g. for implementing HMAC */
39size_t ssh_digest_blocksize(struct ssh_digest_ctx *ctx);
40
41/* Copies internal state of digest of 'from' to 'to' */
42int ssh_digest_copy_state(struct ssh_digest_ctx *from,
43 struct ssh_digest_ctx *to);
44
36/* One-shot API */ 45/* One-shot API */
37int ssh_digest_memory(int alg, const void *m, size_t mlen, 46int ssh_digest_memory(int alg, const void *m, size_t mlen,
38 u_char *d, size_t dlen) 47 u_char *d, size_t dlen)
@@ -42,7 +51,6 @@ int ssh_digest_buffer(int alg, const Buffer *b, u_char *d, size_t dlen)
42 __attribute__((__bounded__(__buffer__, 3, 4))); 51 __attribute__((__bounded__(__buffer__, 3, 4)));
43 52
44/* Update API */ 53/* Update API */
45struct ssh_digest_ctx;
46struct ssh_digest_ctx *ssh_digest_start(int alg); 54struct ssh_digest_ctx *ssh_digest_start(int alg);
47int ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen) 55int ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen)
48 __attribute__((__bounded__(__buffer__, 2, 3))); 56 __attribute__((__bounded__(__buffer__, 2, 3)));
diff --git a/hmac.c b/hmac.c
new file mode 100644
index 000000000..99317b0f9
--- /dev/null
+++ b/hmac.c
@@ -0,0 +1,197 @@
1/* $OpenBSD: hmac.c,v 1.10 2014/01/31 16:39:19 tedu Exp $ */
2/*
3 * Copyright (c) 2014 Markus Friedl. All rights reserved.
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include "includes.h"
19
20#include <sys/types.h>
21#include <string.h>
22
23#include "buffer.h"
24#include "digest.h"
25#include "hmac.h"
26
27struct ssh_hmac_ctx {
28 int alg;
29 struct ssh_digest_ctx *ictx;
30 struct ssh_digest_ctx *octx;
31 struct ssh_digest_ctx *digest;
32 u_char *buf;
33 size_t buf_len;
34};
35
36size_t
37ssh_hmac_bytes(int alg)
38{
39 return ssh_digest_bytes(alg);
40}
41
42struct ssh_hmac_ctx *
43ssh_hmac_start(int alg)
44{
45 struct ssh_hmac_ctx *ret;
46
47 if ((ret = calloc(1, sizeof(*ret))) == NULL)
48 return NULL;
49 ret->alg = alg;
50 if ((ret->ictx = ssh_digest_start(alg)) == NULL ||
51 (ret->octx = ssh_digest_start(alg)) == NULL ||
52 (ret->digest = ssh_digest_start(alg)) == NULL)
53 goto fail;
54 ret->buf_len = ssh_digest_blocksize(ret->ictx);
55 if ((ret->buf = calloc(1, ret->buf_len)) == NULL)
56 goto fail;
57 return ret;
58fail:
59 ssh_hmac_free(ret);
60 return NULL;
61}
62
63int
64ssh_hmac_init(struct ssh_hmac_ctx *ctx, const void *key, size_t klen)
65{
66 size_t i;
67
68 /* reset ictx and octx if no is key given */
69 if (key != NULL) {
70 /* truncate long keys */
71 if (klen <= ctx->buf_len)
72 memcpy(ctx->buf, key, klen);
73 else if (ssh_digest_memory(ctx->alg, key, klen, ctx->buf,
74 ctx->buf_len) < 0)
75 return -1;
76 for (i = 0; i < ctx->buf_len; i++)
77 ctx->buf[i] ^= 0x36;
78 if (ssh_digest_update(ctx->ictx, ctx->buf, ctx->buf_len) < 0)
79 return -1;
80 for (i = 0; i < ctx->buf_len; i++)
81 ctx->buf[i] ^= 0x36 ^ 0x5c;
82 if (ssh_digest_update(ctx->octx, ctx->buf, ctx->buf_len) < 0)
83 return -1;
84 explicit_bzero(ctx->buf, ctx->buf_len);
85 }
86 /* start with ictx */
87 if (ssh_digest_copy_state(ctx->ictx, ctx->digest) < 0)
88 return -1;
89 return 0;
90}
91
92int
93ssh_hmac_update(struct ssh_hmac_ctx *ctx, const void *m, size_t mlen)
94{
95 return ssh_digest_update(ctx->digest, m, mlen);
96}
97
98int
99ssh_hmac_update_buffer(struct ssh_hmac_ctx *ctx, const Buffer *b)
100{
101 return ssh_digest_update_buffer(ctx->digest, b);
102}
103
104int
105ssh_hmac_final(struct ssh_hmac_ctx *ctx, u_char *d, size_t dlen)
106{
107 size_t len;
108
109 len = ssh_digest_bytes(ctx->alg);
110 if (dlen < len ||
111 ssh_digest_final(ctx->digest, ctx->buf, len))
112 return -1;
113 /* switch to octx */
114 if (ssh_digest_copy_state(ctx->octx, ctx->digest) < 0 ||
115 ssh_digest_update(ctx->digest, ctx->buf, len) < 0 ||
116 ssh_digest_final(ctx->digest, d, dlen) < 0)
117 return -1;
118 return 0;
119}
120
121void
122ssh_hmac_free(struct ssh_hmac_ctx *ctx)
123{
124 if (ctx != NULL) {
125 ssh_digest_free(ctx->ictx);
126 ssh_digest_free(ctx->octx);
127 ssh_digest_free(ctx->digest);
128 if (ctx->buf) {
129 explicit_bzero(ctx->buf, ctx->buf_len);
130 free(ctx->buf);
131 }
132 explicit_bzero(ctx, sizeof(*ctx));
133 free(ctx);
134 }
135}
136
137#ifdef TEST
138
139/* cc -DTEST hmac.c digest.c buffer.c cleanup.c fatal.c log.c xmalloc.c -lcrypto */
140static void
141hmac_test(void *key, size_t klen, void *m, size_t mlen, u_char *e, size_t elen)
142{
143 struct ssh_hmac_ctx *ctx;
144 size_t i;
145 u_char digest[16];
146
147 if ((ctx = ssh_hmac_start(SSH_DIGEST_MD5)) == NULL)
148 printf("ssh_hmac_start failed");
149 if (ssh_hmac_init(ctx, key, klen) < 0 ||
150 ssh_hmac_update(ctx, m, mlen) < 0 ||
151 ssh_hmac_final(ctx, digest, sizeof(digest)) < 0)
152 printf("ssh_hmac_xxx failed");
153 ssh_hmac_free(ctx);
154
155 if (memcmp(e, digest, elen)) {
156 for (i = 0; i < elen; i++)
157 printf("[%zd] %2.2x %2.2x\n", i, e[i], digest[i]);
158 printf("mismatch\n");
159 } else
160 printf("ok\n");
161}
162
163int
164main(int argc, char **argv)
165{
166 /* try test vectors from RFC 2104 */
167
168 u_char key1[16] = {
169 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb,
170 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb };
171 u_char *data1 = "Hi There";
172 u_char dig1[16] = {
173 0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c,
174 0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d };
175
176 u_char *key2 = "Jefe";
177 u_char *data2 = "what do ya want for nothing?";
178 u_char dig2[16] = {
179 0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03,
180 0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38 };
181
182 u_char key3[16];
183 u_char data3[50];
184 u_char dig3[16] = {
185 0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88,
186 0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6 };
187 memset(key3, 0xaa, sizeof(key3));
188 memset(data3, 0xdd, sizeof(data3));
189
190 hmac_test(key1, sizeof(key1), data1, strlen(data1), dig1, sizeof(dig1));
191 hmac_test(key2, strlen(key2), data2, strlen(data2), dig2, sizeof(dig2));
192 hmac_test(key3, sizeof(key3), data3, sizeof(data3), dig3, sizeof(dig3));
193
194 return 0;
195}
196
197#endif
diff --git a/hmac.h b/hmac.h
new file mode 100644
index 000000000..2374a6955
--- /dev/null
+++ b/hmac.h
@@ -0,0 +1,37 @@
1/* $OpenBSD: hmac.h,v 1.6 2014/01/27 18:58:14 markus Exp $ */
2/*
3 * Copyright (c) 2014 Markus Friedl. All rights reserved.
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#ifndef _HMAC_H
19#define _HMAC_H
20
21/* Returns the algorithm's digest length in bytes or 0 for invalid algorithm */
22size_t ssh_hmac_bytes(int alg);
23
24struct ssh_hmac_ctx;
25struct ssh_hmac_ctx *ssh_hmac_start(int alg);
26
27/* Sets the state of the HMAC or resets the state if key == NULL */
28int ssh_hmac_init(struct ssh_hmac_ctx *ctx, const void *key, size_t klen)
29 __attribute__((__bounded__(__buffer__, 2, 3)));
30int ssh_hmac_update(struct ssh_hmac_ctx *ctx, const void *m, size_t mlen)
31 __attribute__((__bounded__(__buffer__, 2, 3)));
32int ssh_hmac_update_buffer(struct ssh_hmac_ctx *ctx, const Buffer *b);
33int ssh_hmac_final(struct ssh_hmac_ctx *ctx, u_char *d, size_t dlen)
34 __attribute__((__bounded__(__buffer__, 2, 3)));
35void ssh_hmac_free(struct ssh_hmac_ctx *ctx);
36
37#endif /* _HMAC_H */
diff --git a/hostfile.c b/hostfile.c
index 2778fb5df..0198cd001 100644
--- a/hostfile.c
+++ b/hostfile.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: hostfile.c,v 1.53 2014/01/09 23:20:00 djm Exp $ */ 1/* $OpenBSD: hostfile.c,v 1.54 2014/01/27 18:58:14 markus Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -42,9 +42,6 @@
42 42
43#include <netinet/in.h> 43#include <netinet/in.h>
44 44
45#include <openssl/hmac.h>
46#include <openssl/sha.h>
47
48#include <resolv.h> 45#include <resolv.h>
49#include <stdarg.h> 46#include <stdarg.h>
50#include <stdio.h> 47#include <stdio.h>
@@ -58,6 +55,7 @@
58#include "log.h" 55#include "log.h"
59#include "misc.h" 56#include "misc.h"
60#include "digest.h" 57#include "digest.h"
58#include "hmac.h"
61 59
62struct hostkeys { 60struct hostkeys {
63 struct hostkey_entry *entries; 61 struct hostkey_entry *entries;
@@ -102,9 +100,9 @@ extract_salt(const char *s, u_int l, u_char *salt, size_t salt_len)
102 debug2("extract_salt: salt decode error"); 100 debug2("extract_salt: salt decode error");
103 return (-1); 101 return (-1);
104 } 102 }
105 if (ret != SHA_DIGEST_LENGTH) { 103 if (ret != (int)ssh_hmac_bytes(SSH_DIGEST_SHA1)) {
106 debug2("extract_salt: expected salt len %d, got %d", 104 debug2("extract_salt: expected salt len %zd, got %d",
107 SHA_DIGEST_LENGTH, ret); 105 ssh_hmac_bytes(SSH_DIGEST_SHA1), ret);
108 return (-1); 106 return (-1);
109 } 107 }
110 108
@@ -114,14 +112,13 @@ extract_salt(const char *s, u_int l, u_char *salt, size_t salt_len)
114char * 112char *
115host_hash(const char *host, const char *name_from_hostfile, u_int src_len) 113host_hash(const char *host, const char *name_from_hostfile, u_int src_len)
116{ 114{
117 const EVP_MD *md = EVP_sha1(); 115 struct ssh_hmac_ctx *ctx;
118 HMAC_CTX mac_ctx;
119 u_char salt[256], result[256]; 116 u_char salt[256], result[256];
120 char uu_salt[512], uu_result[512]; 117 char uu_salt[512], uu_result[512];
121 static char encoded[1024]; 118 static char encoded[1024];
122 u_int i, len; 119 u_int i, len;
123 120
124 len = EVP_MD_size(md); 121 len = ssh_digest_bytes(SSH_DIGEST_SHA1);
125 122
126 if (name_from_hostfile == NULL) { 123 if (name_from_hostfile == NULL) {
127 /* Create new salt */ 124 /* Create new salt */
@@ -134,14 +131,16 @@ host_hash(const char *host, const char *name_from_hostfile, u_int src_len)
134 return (NULL); 131 return (NULL);
135 } 132 }
136 133
137 HMAC_Init(&mac_ctx, salt, len, md); 134 if ((ctx = ssh_hmac_start(SSH_DIGEST_SHA1)) == NULL ||
138 HMAC_Update(&mac_ctx, (u_char *)host, strlen(host)); 135 ssh_hmac_init(ctx, salt, len) < 0 ||
139 HMAC_Final(&mac_ctx, result, NULL); 136 ssh_hmac_update(ctx, host, strlen(host)) < 0 ||
140 HMAC_cleanup(&mac_ctx); 137 ssh_hmac_final(ctx, result, sizeof(result)))
138 fatal("%s: ssh_hmac failed", __func__);
139 ssh_hmac_free(ctx);
141 140
142 if (__b64_ntop(salt, len, uu_salt, sizeof(uu_salt)) == -1 || 141 if (__b64_ntop(salt, len, uu_salt, sizeof(uu_salt)) == -1 ||
143 __b64_ntop(result, len, uu_result, sizeof(uu_result)) == -1) 142 __b64_ntop(result, len, uu_result, sizeof(uu_result)) == -1)
144 fatal("host_hash: __b64_ntop failed"); 143 fatal("%s: __b64_ntop failed", __func__);
145 144
146 snprintf(encoded, sizeof(encoded), "%s%s%c%s", HASH_MAGIC, uu_salt, 145 snprintf(encoded, sizeof(encoded), "%s%s%c%s", HASH_MAGIC, uu_salt,
147 HASH_DELIM, uu_result); 146 HASH_DELIM, uu_result);
diff --git a/kex.h b/kex.h
index 1aa3ec26a..c85680eea 100644
--- a/kex.h
+++ b/kex.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: kex.h,v 1.61 2014/01/25 10:12:50 dtucker Exp $ */ 1/* $OpenBSD: kex.h,v 1.62 2014/01/27 18:58:14 markus Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -105,9 +105,8 @@ struct Mac {
105 u_int key_len; 105 u_int key_len;
106 int type; 106 int type;
107 int etm; /* Encrypt-then-MAC */ 107 int etm; /* Encrypt-then-MAC */
108 const EVP_MD *evp_md; 108 struct ssh_hmac_ctx *hmac_ctx;
109 HMAC_CTX evp_ctx; 109 struct umac_ctx *umac_ctx;
110 struct umac_ctx *umac_ctx;
111}; 110};
112struct Comp { 111struct Comp {
113 int type; 112 int type;
diff --git a/mac.c b/mac.c
index d3a0b935f..4c4a6bf53 100644
--- a/mac.c
+++ b/mac.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: mac.c,v 1.26 2014/01/04 17:50:55 tedu Exp $ */ 1/* $OpenBSD: mac.c,v 1.27 2014/01/27 18:58:14 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * 4 *
@@ -27,8 +27,6 @@
27 27
28#include <sys/types.h> 28#include <sys/types.h>
29 29
30#include <openssl/hmac.h>
31
32#include <stdarg.h> 30#include <stdarg.h>
33#include <string.h> 31#include <string.h>
34#include <signal.h> 32#include <signal.h>
@@ -42,18 +40,20 @@
42#include "mac.h" 40#include "mac.h"
43#include "misc.h" 41#include "misc.h"
44 42
43#include "digest.h"
44#include "hmac.h"
45#include "umac.h" 45#include "umac.h"
46 46
47#include "openbsd-compat/openssl-compat.h" 47#include "openbsd-compat/openssl-compat.h"
48 48
49#define SSH_EVP 1 /* OpenSSL EVP-based MAC */ 49#define SSH_DIGEST 1 /* SSH_DIGEST_XXX */
50#define SSH_UMAC 2 /* UMAC (not integrated with OpenSSL) */ 50#define SSH_UMAC 2 /* UMAC (not integrated with OpenSSL) */
51#define SSH_UMAC128 3 51#define SSH_UMAC128 3
52 52
53struct macalg { 53struct macalg {
54 char *name; 54 char *name;
55 int type; 55 int type;
56 const EVP_MD * (*mdfunc)(void); 56 int alg;
57 int truncatebits; /* truncate digest if != 0 */ 57 int truncatebits; /* truncate digest if != 0 */
58 int key_len; /* just for UMAC */ 58 int key_len; /* just for UMAC */
59 int len; /* just for UMAC */ 59 int len; /* just for UMAC */
@@ -62,33 +62,33 @@ struct macalg {
62 62
63static const struct macalg macs[] = { 63static const struct macalg macs[] = {
64 /* Encrypt-and-MAC (encrypt-and-authenticate) variants */ 64 /* Encrypt-and-MAC (encrypt-and-authenticate) variants */
65 { "hmac-sha1", SSH_EVP, EVP_sha1, 0, 0, 0, 0 }, 65 { "hmac-sha1", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 0 },
66 { "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, 0, 0, 0 }, 66 { "hmac-sha1-96", SSH_DIGEST, SSH_DIGEST_SHA1, 96, 0, 0, 0 },
67#ifdef HAVE_EVP_SHA256 67#ifdef HAVE_EVP_SHA256
68 { "hmac-sha2-256", SSH_EVP, EVP_sha256, 0, 0, 0, 0 }, 68 { "hmac-sha2-256", SSH_DIGEST, SSH_DIGEST_SHA256, 0, 0, 0, 0 },
69 { "hmac-sha2-512", SSH_EVP, EVP_sha512, 0, 0, 0, 0 }, 69 { "hmac-sha2-512", SSH_DIGEST, SSH_DIGEST_SHA512, 0, 0, 0, 0 },
70#endif 70#endif
71 { "hmac-md5", SSH_EVP, EVP_md5, 0, 0, 0, 0 }, 71 { "hmac-md5", SSH_DIGEST, SSH_DIGEST_MD5, 0, 0, 0, 0 },
72 { "hmac-md5-96", SSH_EVP, EVP_md5, 96, 0, 0, 0 }, 72 { "hmac-md5-96", SSH_DIGEST, SSH_DIGEST_MD5, 96, 0, 0, 0 },
73 { "hmac-ripemd160", SSH_EVP, EVP_ripemd160, 0, 0, 0, 0 }, 73 { "hmac-ripemd160", SSH_DIGEST, SSH_DIGEST_RIPEMD160, 0, 0, 0, 0 },
74 { "hmac-ripemd160@openssh.com", SSH_EVP, EVP_ripemd160, 0, 0, 0, 0 }, 74 { "hmac-ripemd160@openssh.com", SSH_DIGEST, SSH_DIGEST_RIPEMD160, 0, 0, 0, 0 },
75 { "umac-64@openssh.com", SSH_UMAC, NULL, 0, 128, 64, 0 }, 75 { "umac-64@openssh.com", SSH_UMAC, 0, 0, 128, 64, 0 },
76 { "umac-128@openssh.com", SSH_UMAC128, NULL, 0, 128, 128, 0 }, 76 { "umac-128@openssh.com", SSH_UMAC128, 0, 0, 128, 128, 0 },
77 77
78 /* Encrypt-then-MAC variants */ 78 /* Encrypt-then-MAC variants */
79 { "hmac-sha1-etm@openssh.com", SSH_EVP, EVP_sha1, 0, 0, 0, 1 }, 79 { "hmac-sha1-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 1 },
80 { "hmac-sha1-96-etm@openssh.com", SSH_EVP, EVP_sha1, 96, 0, 0, 1 }, 80 { "hmac-sha1-96-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA1, 96, 0, 0, 1 },
81#ifdef HAVE_EVP_SHA256 81#ifdef HAVE_EVP_SHA256
82 { "hmac-sha2-256-etm@openssh.com", SSH_EVP, EVP_sha256, 0, 0, 0, 1 }, 82 { "hmac-sha2-256-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA256, 0, 0, 0, 1 },
83 { "hmac-sha2-512-etm@openssh.com", SSH_EVP, EVP_sha512, 0, 0, 0, 1 }, 83 { "hmac-sha2-512-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA512, 0, 0, 0, 1 },
84#endif 84#endif
85 { "hmac-md5-etm@openssh.com", SSH_EVP, EVP_md5, 0, 0, 0, 1 }, 85 { "hmac-md5-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_MD5, 0, 0, 0, 1 },
86 { "hmac-md5-96-etm@openssh.com", SSH_EVP, EVP_md5, 96, 0, 0, 1 }, 86 { "hmac-md5-96-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_MD5, 96, 0, 0, 1 },
87 { "hmac-ripemd160-etm@openssh.com", SSH_EVP, EVP_ripemd160, 0, 0, 0, 1 }, 87 { "hmac-ripemd160-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_RIPEMD160, 0, 0, 0, 1 },
88 { "umac-64-etm@openssh.com", SSH_UMAC, NULL, 0, 128, 64, 1 }, 88 { "umac-64-etm@openssh.com", SSH_UMAC, 0, 0, 128, 64, 1 },
89 { "umac-128-etm@openssh.com", SSH_UMAC128, NULL, 0, 128, 128, 1 }, 89 { "umac-128-etm@openssh.com", SSH_UMAC128, 0, 0, 128, 128, 1 },
90 90
91 { NULL, 0, NULL, 0, 0, 0, 0 } 91 { NULL, 0, 0, 0, 0, 0, 0 }
92}; 92};
93 93
94/* Returns a list of supported MACs separated by the specified char. */ 94/* Returns a list of supported MACs separated by the specified char. */
@@ -113,14 +113,11 @@ mac_alg_list(char sep)
113static void 113static void
114mac_setup_by_alg(Mac *mac, const struct macalg *macalg) 114mac_setup_by_alg(Mac *mac, const struct macalg *macalg)
115{ 115{
116 int evp_len;
117
118 mac->type = macalg->type; 116 mac->type = macalg->type;
119 if (mac->type == SSH_EVP) { 117 if (mac->type == SSH_DIGEST) {
120 mac->evp_md = macalg->mdfunc(); 118 if ((mac->hmac_ctx = ssh_hmac_start(macalg->alg)) == NULL)
121 if ((evp_len = EVP_MD_size(mac->evp_md)) <= 0) 119 fatal("ssh_hmac_start(alg=%d) failed", macalg->alg);
122 fatal("mac %s len %d", mac->name, evp_len); 120 mac->key_len = mac->mac_len = ssh_hmac_bytes(macalg->alg);
123 mac->key_len = mac->mac_len = (u_int)evp_len;
124 } else { 121 } else {
125 mac->mac_len = macalg->len / 8; 122 mac->mac_len = macalg->len / 8;
126 mac->key_len = macalg->key_len / 8; 123 mac->key_len = macalg->key_len / 8;
@@ -154,11 +151,10 @@ mac_init(Mac *mac)
154 if (mac->key == NULL) 151 if (mac->key == NULL)
155 fatal("mac_init: no key"); 152 fatal("mac_init: no key");
156 switch (mac->type) { 153 switch (mac->type) {
157 case SSH_EVP: 154 case SSH_DIGEST:
158 if (mac->evp_md == NULL) 155 if (mac->hmac_ctx == NULL ||
156 ssh_hmac_init(mac->hmac_ctx, mac->key, mac->key_len) < 0)
159 return -1; 157 return -1;
160 HMAC_CTX_init(&mac->evp_ctx);
161 HMAC_Init(&mac->evp_ctx, mac->key, mac->key_len, mac->evp_md);
162 return 0; 158 return 0;
163 case SSH_UMAC: 159 case SSH_UMAC:
164 mac->umac_ctx = umac_new(mac->key); 160 mac->umac_ctx = umac_new(mac->key);
@@ -185,13 +181,14 @@ mac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen)
185 mac->mac_len, sizeof(u)); 181 mac->mac_len, sizeof(u));
186 182
187 switch (mac->type) { 183 switch (mac->type) {
188 case SSH_EVP: 184 case SSH_DIGEST:
189 put_u32(b, seqno); 185 put_u32(b, seqno);
190 /* reset HMAC context */ 186 /* reset HMAC context */
191 HMAC_Init(&mac->evp_ctx, NULL, 0, NULL); 187 if (ssh_hmac_init(mac->hmac_ctx, NULL, 0) < 0 ||
192 HMAC_Update(&mac->evp_ctx, b, sizeof(b)); 188 ssh_hmac_update(mac->hmac_ctx, b, sizeof(b)) < 0 ||
193 HMAC_Update(&mac->evp_ctx, data, datalen); 189 ssh_hmac_update(mac->hmac_ctx, data, datalen) < 0 ||
194 HMAC_Final(&mac->evp_ctx, u.m, NULL); 190 ssh_hmac_final(mac->hmac_ctx, u.m, sizeof(u.m)) < 0)
191 fatal("ssh_hmac failed");
195 break; 192 break;
196 case SSH_UMAC: 193 case SSH_UMAC:
197 put_u64(nonce, seqno); 194 put_u64(nonce, seqno);
@@ -218,9 +215,9 @@ mac_clear(Mac *mac)
218 } else if (mac->type == SSH_UMAC128) { 215 } else if (mac->type == SSH_UMAC128) {
219 if (mac->umac_ctx != NULL) 216 if (mac->umac_ctx != NULL)
220 umac128_delete(mac->umac_ctx); 217 umac128_delete(mac->umac_ctx);
221 } else if (mac->evp_md != NULL) 218 } else if (mac->hmac_ctx != NULL)
222 HMAC_cleanup(&mac->evp_ctx); 219 ssh_hmac_free(mac->hmac_ctx);
223 mac->evp_md = NULL; 220 mac->hmac_ctx = NULL;
224 mac->umac_ctx = NULL; 221 mac->umac_ctx = NULL;
225} 222}
226 223