summaryrefslogtreecommitdiff
path: root/mac.c
diff options
context:
space:
mode:
Diffstat (limited to 'mac.c')
-rw-r--r--mac.c83
1 files changed, 54 insertions, 29 deletions
diff --git a/mac.c b/mac.c
index 3f2dc6f2a..c4dfb501d 100644
--- a/mac.c
+++ b/mac.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: mac.c,v 1.21 2012/12/11 22:51:45 sthen Exp $ */ 1/* $OpenBSD: mac.c,v 1.24 2013/06/03 00:03:18 dtucker Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * 4 *
@@ -50,7 +50,7 @@
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 { 53struct macalg {
54 char *name; 54 char *name;
55 int type; 55 int type;
56 const EVP_MD * (*mdfunc)(void); 56 const EVP_MD * (*mdfunc)(void);
@@ -58,7 +58,9 @@ struct {
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 */
60 int etm; /* Encrypt-then-MAC */ 60 int etm; /* Encrypt-then-MAC */
61} macs[] = { 61};
62
63static const struct macalg macs[] = {
62 /* Encrypt-and-MAC (encrypt-and-authenticate) variants */ 64 /* Encrypt-and-MAC (encrypt-and-authenticate) variants */
63 { "hmac-sha1", SSH_EVP, EVP_sha1, 0, 0, 0, 0 }, 65 { "hmac-sha1", SSH_EVP, EVP_sha1, 0, 0, 0, 0 },
64 { "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, 0, 0, 0 }, 66 { "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, 0, 0, 0 },
@@ -89,38 +91,58 @@ struct {
89 { NULL, 0, NULL, 0, 0, 0, 0 } 91 { NULL, 0, NULL, 0, 0, 0, 0 }
90}; 92};
91 93
94/* Returns a comma-separated list of supported MACs. */
95char *
96mac_alg_list(void)
97{
98 char *ret = NULL;
99 size_t nlen, rlen = 0;
100 const struct macalg *m;
101
102 for (m = macs; m->name != NULL; m++) {
103 if (ret != NULL)
104 ret[rlen++] = '\n';
105 nlen = strlen(m->name);
106 ret = xrealloc(ret, 1, rlen + nlen + 2);
107 memcpy(ret + rlen, m->name, nlen + 1);
108 rlen += nlen;
109 }
110 return ret;
111}
112
92static void 113static void
93mac_setup_by_id(Mac *mac, int which) 114mac_setup_by_alg(Mac *mac, const struct macalg *macalg)
94{ 115{
95 int evp_len; 116 int evp_len;
96 mac->type = macs[which].type; 117
118 mac->type = macalg->type;
97 if (mac->type == SSH_EVP) { 119 if (mac->type == SSH_EVP) {
98 mac->evp_md = (*macs[which].mdfunc)(); 120 mac->evp_md = macalg->mdfunc();
99 if ((evp_len = EVP_MD_size(mac->evp_md)) <= 0) 121 if ((evp_len = EVP_MD_size(mac->evp_md)) <= 0)
100 fatal("mac %s len %d", mac->name, evp_len); 122 fatal("mac %s len %d", mac->name, evp_len);
101 mac->key_len = mac->mac_len = (u_int)evp_len; 123 mac->key_len = mac->mac_len = (u_int)evp_len;
102 } else { 124 } else {
103 mac->mac_len = macs[which].len / 8; 125 mac->mac_len = macalg->len / 8;
104 mac->key_len = macs[which].key_len / 8; 126 mac->key_len = macalg->key_len / 8;
105 mac->umac_ctx = NULL; 127 mac->umac_ctx = NULL;
106 } 128 }
107 if (macs[which].truncatebits != 0) 129 if (macalg->truncatebits != 0)
108 mac->mac_len = macs[which].truncatebits / 8; 130 mac->mac_len = macalg->truncatebits / 8;
109 mac->etm = macs[which].etm; 131 mac->etm = macalg->etm;
110} 132}
111 133
112int 134int
113mac_setup(Mac *mac, char *name) 135mac_setup(Mac *mac, char *name)
114{ 136{
115 int i; 137 const struct macalg *m;
116 138
117 for (i = 0; macs[i].name; i++) { 139 for (m = macs; m->name != NULL; m++) {
118 if (strcmp(name, macs[i].name) == 0) { 140 if (strcmp(name, m->name) != 0)
119 if (mac != NULL) 141 continue;
120 mac_setup_by_id(mac, i); 142 if (mac != NULL)
121 debug2("mac_setup: found %s", name); 143 mac_setup_by_alg(mac, m);
122 return (0); 144 debug2("mac_setup: found %s", name);
123 } 145 return (0);
124 } 146 }
125 debug2("mac_setup: unknown %s", name); 147 debug2("mac_setup: unknown %s", name);
126 return (-1); 148 return (-1);
@@ -152,12 +174,15 @@ mac_init(Mac *mac)
152u_char * 174u_char *
153mac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen) 175mac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen)
154{ 176{
155 static u_char m[EVP_MAX_MD_SIZE]; 177 static union {
178 u_char m[EVP_MAX_MD_SIZE];
179 u_int64_t for_align;
180 } u;
156 u_char b[4], nonce[8]; 181 u_char b[4], nonce[8];
157 182
158 if (mac->mac_len > sizeof(m)) 183 if (mac->mac_len > sizeof(u))
159 fatal("mac_compute: mac too long %u %lu", 184 fatal("mac_compute: mac too long %u %lu",
160 mac->mac_len, (u_long)sizeof(m)); 185 mac->mac_len, (u_long)sizeof(u));
161 186
162 switch (mac->type) { 187 switch (mac->type) {
163 case SSH_EVP: 188 case SSH_EVP:
@@ -166,22 +191,22 @@ mac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen)
166 HMAC_Init(&mac->evp_ctx, NULL, 0, NULL); 191 HMAC_Init(&mac->evp_ctx, NULL, 0, NULL);
167 HMAC_Update(&mac->evp_ctx, b, sizeof(b)); 192 HMAC_Update(&mac->evp_ctx, b, sizeof(b));
168 HMAC_Update(&mac->evp_ctx, data, datalen); 193 HMAC_Update(&mac->evp_ctx, data, datalen);
169 HMAC_Final(&mac->evp_ctx, m, NULL); 194 HMAC_Final(&mac->evp_ctx, u.m, NULL);
170 break; 195 break;
171 case SSH_UMAC: 196 case SSH_UMAC:
172 put_u64(nonce, seqno); 197 put_u64(nonce, seqno);
173 umac_update(mac->umac_ctx, data, datalen); 198 umac_update(mac->umac_ctx, data, datalen);
174 umac_final(mac->umac_ctx, m, nonce); 199 umac_final(mac->umac_ctx, u.m, nonce);
175 break; 200 break;
176 case SSH_UMAC128: 201 case SSH_UMAC128:
177 put_u64(nonce, seqno); 202 put_u64(nonce, seqno);
178 umac128_update(mac->umac_ctx, data, datalen); 203 umac128_update(mac->umac_ctx, data, datalen);
179 umac128_final(mac->umac_ctx, m, nonce); 204 umac128_final(mac->umac_ctx, u.m, nonce);
180 break; 205 break;
181 default: 206 default:
182 fatal("mac_compute: unknown MAC type"); 207 fatal("mac_compute: unknown MAC type");
183 } 208 }
184 return (m); 209 return (u.m);
185} 210}
186 211
187void 212void
@@ -213,13 +238,13 @@ mac_valid(const char *names)
213 (p = strsep(&cp, MAC_SEP))) { 238 (p = strsep(&cp, MAC_SEP))) {
214 if (mac_setup(NULL, p) < 0) { 239 if (mac_setup(NULL, p) < 0) {
215 debug("bad mac %s [%s]", p, names); 240 debug("bad mac %s [%s]", p, names);
216 xfree(maclist); 241 free(maclist);
217 return (0); 242 return (0);
218 } else { 243 } else {
219 debug3("mac ok: %s [%s]", p, names); 244 debug3("mac ok: %s [%s]", p, names);
220 } 245 }
221 } 246 }
222 debug3("macs ok: [%s]", names); 247 debug3("macs ok: [%s]", names);
223 xfree(maclist); 248 free(maclist);
224 return (1); 249 return (1);
225} 250}