diff options
Diffstat (limited to 'mac.c')
-rw-r--r-- | mac.c | 94 |
1 files changed, 45 insertions, 49 deletions
@@ -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.28 2014/02/07 06:55:54 djm 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 | ||
53 | struct macalg { | 53 | struct 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 | ||
63 | static const struct macalg macs[] = { | 63 | static 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) | |||
113 | static void | 113 | static void |
114 | mac_setup_by_alg(Mac *mac, const struct macalg *macalg) | 114 | mac_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; |
@@ -139,9 +136,10 @@ mac_setup(Mac *mac, char *name) | |||
139 | for (m = macs; m->name != NULL; m++) { | 136 | for (m = macs; m->name != NULL; m++) { |
140 | if (strcmp(name, m->name) != 0) | 137 | if (strcmp(name, m->name) != 0) |
141 | continue; | 138 | continue; |
142 | if (mac != NULL) | 139 | if (mac != NULL) { |
143 | mac_setup_by_alg(mac, m); | 140 | mac_setup_by_alg(mac, m); |
144 | debug2("mac_setup: found %s", name); | 141 | debug2("mac_setup: setup %s", name); |
142 | } | ||
145 | return (0); | 143 | return (0); |
146 | } | 144 | } |
147 | debug2("mac_setup: unknown %s", name); | 145 | debug2("mac_setup: unknown %s", name); |
@@ -152,13 +150,12 @@ int | |||
152 | mac_init(Mac *mac) | 150 | mac_init(Mac *mac) |
153 | { | 151 | { |
154 | if (mac->key == NULL) | 152 | if (mac->key == NULL) |
155 | fatal("mac_init: no key"); | 153 | fatal("%s: no key", __func__); |
156 | switch (mac->type) { | 154 | switch (mac->type) { |
157 | case SSH_EVP: | 155 | case SSH_DIGEST: |
158 | if (mac->evp_md == NULL) | 156 | if (mac->hmac_ctx == NULL || |
157 | ssh_hmac_init(mac->hmac_ctx, mac->key, mac->key_len) < 0) | ||
159 | return -1; | 158 | 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; | 159 | return 0; |
163 | case SSH_UMAC: | 160 | case SSH_UMAC: |
164 | mac->umac_ctx = umac_new(mac->key); | 161 | mac->umac_ctx = umac_new(mac->key); |
@@ -185,13 +182,14 @@ mac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen) | |||
185 | mac->mac_len, sizeof(u)); | 182 | mac->mac_len, sizeof(u)); |
186 | 183 | ||
187 | switch (mac->type) { | 184 | switch (mac->type) { |
188 | case SSH_EVP: | 185 | case SSH_DIGEST: |
189 | put_u32(b, seqno); | 186 | put_u32(b, seqno); |
190 | /* reset HMAC context */ | 187 | /* reset HMAC context */ |
191 | HMAC_Init(&mac->evp_ctx, NULL, 0, NULL); | 188 | if (ssh_hmac_init(mac->hmac_ctx, NULL, 0) < 0 || |
192 | HMAC_Update(&mac->evp_ctx, b, sizeof(b)); | 189 | ssh_hmac_update(mac->hmac_ctx, b, sizeof(b)) < 0 || |
193 | HMAC_Update(&mac->evp_ctx, data, datalen); | 190 | ssh_hmac_update(mac->hmac_ctx, data, datalen) < 0 || |
194 | HMAC_Final(&mac->evp_ctx, u.m, NULL); | 191 | ssh_hmac_final(mac->hmac_ctx, u.m, sizeof(u.m)) < 0) |
192 | fatal("ssh_hmac failed"); | ||
195 | break; | 193 | break; |
196 | case SSH_UMAC: | 194 | case SSH_UMAC: |
197 | put_u64(nonce, seqno); | 195 | put_u64(nonce, seqno); |
@@ -218,9 +216,9 @@ mac_clear(Mac *mac) | |||
218 | } else if (mac->type == SSH_UMAC128) { | 216 | } else if (mac->type == SSH_UMAC128) { |
219 | if (mac->umac_ctx != NULL) | 217 | if (mac->umac_ctx != NULL) |
220 | umac128_delete(mac->umac_ctx); | 218 | umac128_delete(mac->umac_ctx); |
221 | } else if (mac->evp_md != NULL) | 219 | } else if (mac->hmac_ctx != NULL) |
222 | HMAC_cleanup(&mac->evp_ctx); | 220 | ssh_hmac_free(mac->hmac_ctx); |
223 | mac->evp_md = NULL; | 221 | mac->hmac_ctx = NULL; |
224 | mac->umac_ctx = NULL; | 222 | mac->umac_ctx = NULL; |
225 | } | 223 | } |
226 | 224 | ||
@@ -240,8 +238,6 @@ mac_valid(const char *names) | |||
240 | debug("bad mac %s [%s]", p, names); | 238 | debug("bad mac %s [%s]", p, names); |
241 | free(maclist); | 239 | free(maclist); |
242 | return (0); | 240 | return (0); |
243 | } else { | ||
244 | debug3("mac ok: %s [%s]", p, names); | ||
245 | } | 241 | } |
246 | } | 242 | } |
247 | debug3("macs ok: [%s]", names); | 243 | debug3("macs ok: [%s]", names); |