defatal mac.[ch]

Conflicts:

	ssh/packet.c
This commit is contained in:
Markus Friedl
2012-01-17 14:42:52 +01:00
parent ef0c2e123f
commit 568a12a63e
5 changed files with 92 additions and 66 deletions

View File

@@ -27,9 +27,10 @@
#define KEX_H
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/ec.h>
#include "mac.h"
#define KEX_COOKIE_LEN 16
#define KEX_DH1 "diffie-hellman-group1-sha1"
@@ -76,7 +77,7 @@ enum kex_exchange {
#define KEX_INIT_SENT 0x0001
typedef struct Kex Kex;
typedef struct Mac Mac;
typedef struct sshmac Mac;
typedef struct Comp Comp;
typedef struct Enc Enc;
typedef struct Newkeys Newkeys;
@@ -90,17 +91,6 @@ struct Enc {
u_char *key;
u_char *iv;
};
struct Mac {
char *name;
int enabled;
u_int mac_len;
u_char *key;
u_int key_len;
int type;
const EVP_MD *evp_md;
HMAC_CTX evp_ctx;
struct umac_ctx *umac_ctx;
};
struct Comp {
int type;
int enabled;

View File

@@ -38,6 +38,7 @@
#include "kex.h"
#include "mac.h"
#include "misc.h"
#include "err.h"
#include "umac.h"
@@ -66,7 +67,7 @@ struct {
{ NULL, 0, NULL, 0, -1, -1 }
};
static void
static int
mac_setup_by_id(Mac *mac, int which)
{
int evp_len;
@@ -74,7 +75,7 @@ mac_setup_by_id(Mac *mac, int which)
if (mac->type == SSH_EVP) {
mac->evp_md = (*macs[which].mdfunc)();
if ((evp_len = EVP_MD_size(mac->evp_md)) <= 0)
fatal("mac %s len %d", mac->name, evp_len);
return SSH_ERR_LIBCRYPTO_ERROR;
mac->key_len = mac->mac_len = (u_int)evp_len;
} else {
mac->mac_len = macs[which].len / 8;
@@ -83,6 +84,7 @@ mac_setup_by_id(Mac *mac, int which)
}
if (macs[which].truncatebits != 0)
mac->mac_len = macs[which].truncatebits / 8;
return 0;
}
int
@@ -93,63 +95,72 @@ mac_setup(Mac *mac, char *name)
for (i = 0; macs[i].name; i++) {
if (strcmp(name, macs[i].name) == 0) {
if (mac != NULL)
mac_setup_by_id(mac, i);
debug2("mac_setup: found %s", name);
return (0);
return mac_setup_by_id(mac, i);
return 0;
}
}
debug2("mac_setup: unknown %s", name);
return (-1);
return SSH_ERR_INVALID_ARGUMENT;
}
int
mac_init(Mac *mac)
{
if (mac->key == NULL)
fatal("mac_init: no key");
return SSH_ERR_INVALID_ARGUMENT;
switch (mac->type) {
case SSH_EVP:
if (mac->evp_md == NULL)
return -1;
return SSH_ERR_INVALID_ARGUMENT;
HMAC_CTX_init(&mac->evp_ctx);
HMAC_Init(&mac->evp_ctx, mac->key, mac->key_len, mac->evp_md);
if (HMAC_Init(&mac->evp_ctx, mac->key, mac->key_len,
mac->evp_md) != 1) {
HMAC_CTX_cleanup(&mac->evp_ctx);
return SSH_ERR_LIBCRYPTO_ERROR;
}
return 0;
case SSH_UMAC:
mac->umac_ctx = umac_new(mac->key);
if ((mac->umac_ctx = umac_new(mac->key)) == NULL)
return SSH_ERR_ALLOC_FAIL;
return 0;
default:
return -1;
return SSH_ERR_INVALID_ARGUMENT;
}
}
u_char *
mac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen)
int
mac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen,
u_char *digest, size_t dlen)
{
static u_char m[EVP_MAX_MD_SIZE];
static u_char m[MAC_DIGEST_LEN_MAX];
u_char b[4], nonce[8];
if (mac->mac_len > sizeof(m))
fatal("mac_compute: mac too long %u %lu",
mac->mac_len, (u_long)sizeof(m));
return SSH_ERR_INTERNAL_ERROR;
switch (mac->type) {
case SSH_EVP:
put_u32(b, seqno);
POKE_U32(b, seqno);
/* reset HMAC context */
HMAC_Init(&mac->evp_ctx, NULL, 0, NULL);
HMAC_Update(&mac->evp_ctx, b, sizeof(b));
HMAC_Update(&mac->evp_ctx, data, datalen);
HMAC_Final(&mac->evp_ctx, m, NULL);
if (HMAC_Init(&mac->evp_ctx, NULL, 0, NULL) != 1 ||
HMAC_Update(&mac->evp_ctx, b, sizeof(b)) != 1 ||
HMAC_Update(&mac->evp_ctx, data, datalen) != 1 ||
HMAC_Final(&mac->evp_ctx, m, NULL) != 1)
return SSH_ERR_LIBCRYPTO_ERROR;
break;
case SSH_UMAC:
put_u64(nonce, seqno);
POKE_U64(nonce, seqno);
umac_update(mac->umac_ctx, data, datalen);
umac_final(mac->umac_ctx, m, nonce);
break;
default:
fatal("mac_compute: unknown MAC type");
return SSH_ERR_INVALID_ARGUMENT;
}
return (m);
if (digest != NULL) {
if (dlen > mac->mac_len)
dlen = mac->mac_len;
memcpy(digest, m, dlen);
}
return 0;
}
void
@@ -172,19 +183,16 @@ mac_valid(const char *names)
char *maclist, *cp, *p;
if (names == NULL || strcmp(names, "") == 0)
return (0);
maclist = cp = xstrdup(names);
return 0;
if ((maclist = cp = xstrdup(names)) == NULL)
return 0;
for ((p = strsep(&cp, MAC_SEP)); p && *p != '\0';
(p = strsep(&cp, MAC_SEP))) {
if (mac_setup(NULL, p) < 0) {
debug("bad mac %s [%s]", p, names);
xfree(maclist);
return (0);
} else {
debug3("mac ok: %s [%s]", p, names);
free(maclist);
return 0;
}
}
debug3("macs ok: [%s]", names);
xfree(maclist);
return (1);
free(maclist);
return 1;
}

View File

@@ -23,8 +23,32 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SSHMAC_H
#define SSHMAC_H
#include <sys/types.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#define MAC_DIGEST_LEN_MAX EVP_MAX_MD_SIZE
struct sshmac {
char *name;
int enabled;
u_int mac_len;
u_char *key;
u_int key_len;
int type;
const EVP_MD *evp_md;
HMAC_CTX evp_ctx;
struct umac_ctx *umac_ctx;
};
int mac_valid(const char *);
int mac_setup(Mac *, char *);
int mac_init(Mac *);
u_char *mac_compute(Mac *, u_int32_t, u_char *, int);
void mac_clear(Mac *);
int mac_setup(struct sshmac *, char *);
int mac_init(struct sshmac *);
int mac_compute(struct sshmac *, u_int32_t, u_char *, int,
u_char *, size_t);
void mac_clear(struct sshmac *);
#endif /* SSHMAC_H */

View File

@@ -298,8 +298,8 @@ ssh_packet_stop_discard(struct ssh *ssh)
fatal("%s: %s", __func__, ssh_err(r));
(void) mac_compute(state->packet_discard_mac,
state->p_read.seqnr,
sshbuf_ptr(state->incoming_packet),
PACKET_MAX_SIZE);
sshbuf_ptr(state->incoming_packet), PACKET_MAX_SIZE,
NULL, 0);
}
logit("Finished discarding for %.200s", get_remote_ipaddr());
cleanup_exit(255);
@@ -856,8 +856,9 @@ ssh_set_newkeys(struct ssh *ssh, int mode)
enc = &state->newkeys[mode]->enc;
mac = &state->newkeys[mode]->mac;
comp = &state->newkeys[mode]->comp;
if (mac_init(mac) == 0)
mac->enabled = 1;
if ((r = mac_init(mac)) != 0)
fatal("newkeys: mac_init_failed: %s", ssh_err(r));
mac->enabled = 1;
DBG(debug("cipher_init_context: %d", mode));
if ((r = cipher_init(cc, enc->cipher, enc->key, enc->key_len,
enc->iv, enc->block_size, crypt_type)) != 0)
@@ -934,7 +935,7 @@ int
ssh_packet_send2_wrapped(struct ssh *ssh)
{
struct session_state *state = ssh->state;
u_char type, *cp, *macbuf = NULL;
u_char type, *cp, macbuf[MAC_DIGEST_LEN_MAX];
u_char padlen, pad;
u_int packet_length = 0;
u_int i, len;
@@ -1021,9 +1022,11 @@ ssh_packet_send2_wrapped(struct ssh *ssh)
/* compute MAC over seqnr and packet(length fields, payload, padding) */
if (mac && mac->enabled) {
macbuf = mac_compute(mac, state->p_send.seqnr,
if ((r = mac_compute(mac, state->p_send.seqnr,
sshbuf_ptr(state->outgoing_packet),
sshbuf_len(state->outgoing_packet));
sshbuf_len(state->outgoing_packet),
macbuf, sizeof(macbuf))) != 0)
goto out;
DBG(debug("done calc MAC out #%d", state->p_send.seqnr));
}
/* encrypt packet and append to output buffer. */
@@ -1374,7 +1377,7 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
{
struct session_state *state = ssh->state;
u_int padlen, need;
u_char *macbuf, *cp;
u_char macbuf[MAC_DIGEST_LEN_MAX], *cp;
u_int maclen, block_size;
Enc *enc = NULL;
Mac *mac = NULL;
@@ -1457,10 +1460,12 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
* increment sequence number for incoming packet
*/
if (mac && mac->enabled) {
macbuf = mac_compute(mac, state->p_read.seqnr,
if ((r = mac_compute(mac, state->p_read.seqnr,
sshbuf_ptr(state->incoming_packet),
sshbuf_len(state->incoming_packet));
if (timingsafe_bcmp(macbuf, sshbuf_ptr(state->input),
sshbuf_len(state->incoming_packet),
macbuf, sizeof(macbuf))) != 0)
goto out;
if (timingsafe_bcmp(macbuf, buffer_ptr(state->input),
mac->mac_len) != 0) {
logit("Corrupted MAC on input.");
if (need > PACKET_MAX_SIZE)

View File

@@ -66,7 +66,6 @@
#include <sys/types.h>
#include <sys/endian.h>
#include "xmalloc.h"
#include "umac.h"
#include <string.h>
#include <stdlib.h>
@@ -1197,7 +1196,7 @@ int umac_delete(struct umac_ctx *ctx)
if (ctx) {
if (ALLOC_BOUNDARY)
ctx = (struct umac_ctx *)ctx->free_ptr;
xfree(ctx);
free(ctx);
}
return (1);
}
@@ -1213,7 +1212,7 @@ struct umac_ctx *umac_new(u_char key[])
size_t bytes_to_add;
aes_int_key prf_key;
octx = ctx = xmalloc(sizeof(*ctx) + ALLOC_BOUNDARY);
octx = ctx = malloc(sizeof(*ctx) + ALLOC_BOUNDARY);
if (ctx) {
if (ALLOC_BOUNDARY) {
bytes_to_add = ALLOC_BOUNDARY -