diff options
author | markus@openbsd.org <markus@openbsd.org> | 2015-01-13 19:31:40 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2015-01-14 20:43:11 +1100 |
commit | 128343bcdb0b60fc826f2733df8cf979ec1627b4 (patch) | |
tree | ec2b30d15b28ee4e5f3822493989fad1e00199f6 /mac.c | |
parent | e7fd952f4ea01f09ceb068721a5431ac2fd416ed (diff) |
upstream commit
adapt mac.c to ssherr.h return codes (de-fatal) and
simplify dependencies ok djm@
Diffstat (limited to 'mac.c')
-rw-r--r-- | mac.c | 93 |
1 files changed, 47 insertions, 46 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: mac.c,v 1.30 2014/04/30 19:07:48 naddy Exp $ */ | 1 | /* $OpenBSD: mac.c,v 1.31 2015/01/13 19:31:40 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,22 +27,16 @@ | |||
27 | 27 | ||
28 | #include <sys/types.h> | 28 | #include <sys/types.h> |
29 | 29 | ||
30 | #include <stdarg.h> | ||
31 | #include <string.h> | 30 | #include <string.h> |
32 | #include <signal.h> | 31 | #include <stdio.h> |
33 | |||
34 | #include "xmalloc.h" | ||
35 | #include "log.h" | ||
36 | #include "cipher.h" | ||
37 | #include "buffer.h" | ||
38 | #include "key.h" | ||
39 | #include "kex.h" | ||
40 | #include "mac.h" | ||
41 | #include "misc.h" | ||
42 | 32 | ||
43 | #include "digest.h" | 33 | #include "digest.h" |
44 | #include "hmac.h" | 34 | #include "hmac.h" |
45 | #include "umac.h" | 35 | #include "umac.h" |
36 | #include "mac.h" | ||
37 | #include "misc.h" | ||
38 | #include "ssherr.h" | ||
39 | #include "sshbuf.h" | ||
46 | 40 | ||
47 | #include "openbsd-compat/openssl-compat.h" | 41 | #include "openbsd-compat/openssl-compat.h" |
48 | 42 | ||
@@ -95,7 +89,7 @@ static const struct macalg macs[] = { | |||
95 | char * | 89 | char * |
96 | mac_alg_list(char sep) | 90 | mac_alg_list(char sep) |
97 | { | 91 | { |
98 | char *ret = NULL; | 92 | char *ret = NULL, *tmp; |
99 | size_t nlen, rlen = 0; | 93 | size_t nlen, rlen = 0; |
100 | const struct macalg *m; | 94 | const struct macalg *m; |
101 | 95 | ||
@@ -103,20 +97,24 @@ mac_alg_list(char sep) | |||
103 | if (ret != NULL) | 97 | if (ret != NULL) |
104 | ret[rlen++] = sep; | 98 | ret[rlen++] = sep; |
105 | nlen = strlen(m->name); | 99 | nlen = strlen(m->name); |
106 | ret = xrealloc(ret, 1, rlen + nlen + 2); | 100 | if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) { |
101 | free(ret); | ||
102 | return NULL; | ||
103 | } | ||
104 | ret = tmp; | ||
107 | memcpy(ret + rlen, m->name, nlen + 1); | 105 | memcpy(ret + rlen, m->name, nlen + 1); |
108 | rlen += nlen; | 106 | rlen += nlen; |
109 | } | 107 | } |
110 | return ret; | 108 | return ret; |
111 | } | 109 | } |
112 | 110 | ||
113 | static void | 111 | static int |
114 | mac_setup_by_alg(Mac *mac, const struct macalg *macalg) | 112 | mac_setup_by_alg(struct sshmac *mac, const struct macalg *macalg) |
115 | { | 113 | { |
116 | mac->type = macalg->type; | 114 | mac->type = macalg->type; |
117 | if (mac->type == SSH_DIGEST) { | 115 | if (mac->type == SSH_DIGEST) { |
118 | if ((mac->hmac_ctx = ssh_hmac_start(macalg->alg)) == NULL) | 116 | if ((mac->hmac_ctx = ssh_hmac_start(macalg->alg)) == NULL) |
119 | fatal("ssh_hmac_start(alg=%d) failed", macalg->alg); | 117 | return SSH_ERR_ALLOC_FAIL; |
120 | mac->key_len = mac->mac_len = ssh_hmac_bytes(macalg->alg); | 118 | mac->key_len = mac->mac_len = ssh_hmac_bytes(macalg->alg); |
121 | } else { | 119 | } else { |
122 | mac->mac_len = macalg->len / 8; | 120 | mac->mac_len = macalg->len / 8; |
@@ -126,61 +124,60 @@ mac_setup_by_alg(Mac *mac, const struct macalg *macalg) | |||
126 | if (macalg->truncatebits != 0) | 124 | if (macalg->truncatebits != 0) |
127 | mac->mac_len = macalg->truncatebits / 8; | 125 | mac->mac_len = macalg->truncatebits / 8; |
128 | mac->etm = macalg->etm; | 126 | mac->etm = macalg->etm; |
127 | return 0; | ||
129 | } | 128 | } |
130 | 129 | ||
131 | int | 130 | int |
132 | mac_setup(Mac *mac, char *name) | 131 | mac_setup(struct sshmac *mac, char *name) |
133 | { | 132 | { |
134 | const struct macalg *m; | 133 | const struct macalg *m; |
135 | 134 | ||
136 | for (m = macs; m->name != NULL; m++) { | 135 | for (m = macs; m->name != NULL; m++) { |
137 | if (strcmp(name, m->name) != 0) | 136 | if (strcmp(name, m->name) != 0) |
138 | continue; | 137 | continue; |
139 | if (mac != NULL) { | 138 | if (mac != NULL) |
140 | mac_setup_by_alg(mac, m); | 139 | return mac_setup_by_alg(mac, m); |
141 | debug2("mac_setup: setup %s", name); | 140 | return 0; |
142 | } | ||
143 | return (0); | ||
144 | } | 141 | } |
145 | debug2("mac_setup: unknown %s", name); | 142 | return SSH_ERR_INVALID_ARGUMENT; |
146 | return (-1); | ||
147 | } | 143 | } |
148 | 144 | ||
149 | int | 145 | int |
150 | mac_init(Mac *mac) | 146 | mac_init(struct sshmac *mac) |
151 | { | 147 | { |
152 | if (mac->key == NULL) | 148 | if (mac->key == NULL) |
153 | fatal("%s: no key", __func__); | 149 | return SSH_ERR_INVALID_ARGUMENT; |
154 | switch (mac->type) { | 150 | switch (mac->type) { |
155 | case SSH_DIGEST: | 151 | case SSH_DIGEST: |
156 | if (mac->hmac_ctx == NULL || | 152 | if (mac->hmac_ctx == NULL || |
157 | ssh_hmac_init(mac->hmac_ctx, mac->key, mac->key_len) < 0) | 153 | ssh_hmac_init(mac->hmac_ctx, mac->key, mac->key_len) < 0) |
158 | return -1; | 154 | return SSH_ERR_INVALID_ARGUMENT; |
159 | return 0; | 155 | return 0; |
160 | case SSH_UMAC: | 156 | case SSH_UMAC: |
161 | mac->umac_ctx = umac_new(mac->key); | 157 | if ((mac->umac_ctx = umac_new(mac->key)) == NULL) |
158 | return SSH_ERR_ALLOC_FAIL; | ||
162 | return 0; | 159 | return 0; |
163 | case SSH_UMAC128: | 160 | case SSH_UMAC128: |
164 | mac->umac_ctx = umac128_new(mac->key); | 161 | mac->umac_ctx = umac128_new(mac->key); |
165 | return 0; | 162 | return 0; |
166 | default: | 163 | default: |
167 | return -1; | 164 | return SSH_ERR_INVALID_ARGUMENT; |
168 | } | 165 | } |
169 | } | 166 | } |
170 | 167 | ||
171 | u_char * | 168 | int |
172 | mac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen) | 169 | mac_compute(struct sshmac *mac, u_int32_t seqno, const u_char *data, int datalen, |
170 | u_char *digest, size_t dlen) | ||
173 | { | 171 | { |
174 | static union { | 172 | static union { |
175 | u_char m[EVP_MAX_MD_SIZE]; | 173 | u_char m[SSH_DIGEST_MAX_LENGTH]; |
176 | u_int64_t for_align; | 174 | u_int64_t for_align; |
177 | } u; | 175 | } u; |
178 | u_char b[4]; | 176 | u_char b[4]; |
179 | u_char nonce[8]; | 177 | u_char nonce[8]; |
180 | 178 | ||
181 | if (mac->mac_len > sizeof(u)) | 179 | if (mac->mac_len > sizeof(u)) |
182 | fatal("mac_compute: mac too long %u %zu", | 180 | return SSH_ERR_INTERNAL_ERROR; |
183 | mac->mac_len, sizeof(u)); | ||
184 | 181 | ||
185 | switch (mac->type) { | 182 | switch (mac->type) { |
186 | case SSH_DIGEST: | 183 | case SSH_DIGEST: |
@@ -190,10 +187,10 @@ mac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen) | |||
190 | ssh_hmac_update(mac->hmac_ctx, b, sizeof(b)) < 0 || | 187 | ssh_hmac_update(mac->hmac_ctx, b, sizeof(b)) < 0 || |
191 | ssh_hmac_update(mac->hmac_ctx, data, datalen) < 0 || | 188 | ssh_hmac_update(mac->hmac_ctx, data, datalen) < 0 || |
192 | ssh_hmac_final(mac->hmac_ctx, u.m, sizeof(u.m)) < 0) | 189 | ssh_hmac_final(mac->hmac_ctx, u.m, sizeof(u.m)) < 0) |
193 | fatal("ssh_hmac failed"); | 190 | return SSH_ERR_LIBCRYPTO_ERROR; |
194 | break; | 191 | break; |
195 | case SSH_UMAC: | 192 | case SSH_UMAC: |
196 | put_u64(nonce, seqno); | 193 | POKE_U64(nonce, seqno); |
197 | umac_update(mac->umac_ctx, data, datalen); | 194 | umac_update(mac->umac_ctx, data, datalen); |
198 | umac_final(mac->umac_ctx, u.m, nonce); | 195 | umac_final(mac->umac_ctx, u.m, nonce); |
199 | break; | 196 | break; |
@@ -203,13 +200,18 @@ mac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen) | |||
203 | umac128_final(mac->umac_ctx, u.m, nonce); | 200 | umac128_final(mac->umac_ctx, u.m, nonce); |
204 | break; | 201 | break; |
205 | default: | 202 | default: |
206 | fatal("mac_compute: unknown MAC type"); | 203 | return SSH_ERR_INVALID_ARGUMENT; |
207 | } | 204 | } |
208 | return (u.m); | 205 | if (digest != NULL) { |
206 | if (dlen > mac->mac_len) | ||
207 | dlen = mac->mac_len; | ||
208 | memcpy(digest, u.m, dlen); | ||
209 | } | ||
210 | return 0; | ||
209 | } | 211 | } |
210 | 212 | ||
211 | void | 213 | void |
212 | mac_clear(Mac *mac) | 214 | mac_clear(struct sshmac *mac) |
213 | { | 215 | { |
214 | if (mac->type == SSH_UMAC) { | 216 | if (mac->type == SSH_UMAC) { |
215 | if (mac->umac_ctx != NULL) | 217 | if (mac->umac_ctx != NULL) |
@@ -231,17 +233,16 @@ mac_valid(const char *names) | |||
231 | char *maclist, *cp, *p; | 233 | char *maclist, *cp, *p; |
232 | 234 | ||
233 | if (names == NULL || strcmp(names, "") == 0) | 235 | if (names == NULL || strcmp(names, "") == 0) |
234 | return (0); | 236 | return 0; |
235 | maclist = cp = xstrdup(names); | 237 | if ((maclist = cp = strdup(names)) == NULL) |
238 | return 0; | ||
236 | for ((p = strsep(&cp, MAC_SEP)); p && *p != '\0'; | 239 | for ((p = strsep(&cp, MAC_SEP)); p && *p != '\0'; |
237 | (p = strsep(&cp, MAC_SEP))) { | 240 | (p = strsep(&cp, MAC_SEP))) { |
238 | if (mac_setup(NULL, p) < 0) { | 241 | if (mac_setup(NULL, p) < 0) { |
239 | debug("bad mac %s [%s]", p, names); | ||
240 | free(maclist); | 242 | free(maclist); |
241 | return (0); | 243 | return 0; |
242 | } | 244 | } |
243 | } | 245 | } |
244 | debug3("macs ok: [%s]", names); | ||
245 | free(maclist); | 246 | free(maclist); |
246 | return (1); | 247 | return 1; |
247 | } | 248 | } |