[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@
This commit is contained in:
Damien Miller 2014-02-04 11:02:42 +11:00
parent 69d0d09f76
commit 4e8d937af7
9 changed files with 332 additions and 71 deletions

View File

@ -1,3 +1,10 @@
20140204
- OpenBSD CVS Sync
- 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@
20140131
- (djm) [sandbox-seccomp-filter.c sandbox-systrace.c] Allow shutdown(2)
syscall from sandboxes; it may be called by packet_close.

View File

@ -1,4 +1,4 @@
# $Id: Makefile.in,v 1.353 2014/01/31 22:25:19 tim Exp $
# $Id: Makefile.in,v 1.354 2014/02/04 00:02:43 djm Exp $
# uncomment if you run a non bourne compatable shell. Ie. csh
#SHELL = @SH@
@ -75,7 +75,7 @@ LIBSSH_OBJS=authfd.o authfile.o bufaux.o bufbn.o buffer.o \
msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \
jpake.o schnorr.o ssh-pkcs11.o krl.o smult_curve25519_ref.o \
kexc25519.o kexc25519c.o poly1305.o chacha.o cipher-chachapoly.o \
ssh-ed25519.o digest.o \
ssh-ed25519.o digest.o hmac.o \
sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o blocks.o
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \

View File

@ -1,4 +1,4 @@
/* $OpenBSD: digest.c,v 1.3 2014/01/20 00:08:48 djm Exp $ */
/* $OpenBSD: digest.c,v 1.4 2014/01/27 18:58:14 markus Exp $ */
/*
* Copyright (c) 2013 Damien Miller <djm@mindrot.org>
*
@ -72,6 +72,12 @@ ssh_digest_bytes(int alg)
return digest == NULL ? 0 : digest->digest_len;
}
size_t
ssh_digest_blocksize(struct ssh_digest_ctx *ctx)
{
return EVP_MD_CTX_block_size(&ctx->mdctx);
}
struct ssh_digest_ctx *
ssh_digest_start(int alg)
{
@ -89,6 +95,15 @@ ssh_digest_start(int alg)
return ret;
}
int
ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to)
{
/* we have bcopy-style order while openssl has memcpy-style */
if (!EVP_MD_CTX_copy_ex(&to->mdctx, &from->mdctx))
return -1;
return 0;
}
int
ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen)
{
@ -123,9 +138,11 @@ ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen)
void
ssh_digest_free(struct ssh_digest_ctx *ctx)
{
EVP_MD_CTX_cleanup(&ctx->mdctx);
memset(ctx, 0, sizeof(*ctx));
free(ctx);
if (ctx != NULL) {
EVP_MD_CTX_cleanup(&ctx->mdctx);
memset(ctx, 0, sizeof(*ctx));
free(ctx);
}
}
int

View File

@ -1,4 +1,4 @@
/* $OpenBSD: digest.h,v 1.1 2014/01/09 23:20:00 djm Exp $ */
/* $OpenBSD: digest.h,v 1.2 2014/01/27 18:58:14 markus Exp $ */
/*
* Copyright (c) 2013 Damien Miller <djm@mindrot.org>
*
@ -30,9 +30,18 @@
#define SSH_DIGEST_SHA512 5
#define SSH_DIGEST_MAX 6
struct ssh_digest_ctx;
/* Returns the algorithm's digest length in bytes or 0 for invalid algorithm */
size_t ssh_digest_bytes(int alg);
/* Returns the block size of the digest, e.g. for implementing HMAC */
size_t ssh_digest_blocksize(struct ssh_digest_ctx *ctx);
/* Copies internal state of digest of 'from' to 'to' */
int ssh_digest_copy_state(struct ssh_digest_ctx *from,
struct ssh_digest_ctx *to);
/* One-shot API */
int ssh_digest_memory(int alg, const void *m, size_t mlen,
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)
__attribute__((__bounded__(__buffer__, 3, 4)));
/* Update API */
struct ssh_digest_ctx;
struct ssh_digest_ctx *ssh_digest_start(int alg);
int ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen)
__attribute__((__bounded__(__buffer__, 2, 3)));

197
hmac.c Normal file
View File

@ -0,0 +1,197 @@
/* $OpenBSD: hmac.c,v 1.10 2014/01/31 16:39:19 tedu Exp $ */
/*
* Copyright (c) 2014 Markus Friedl. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#include <sys/types.h>
#include <string.h>
#include "buffer.h"
#include "digest.h"
#include "hmac.h"
struct ssh_hmac_ctx {
int alg;
struct ssh_digest_ctx *ictx;
struct ssh_digest_ctx *octx;
struct ssh_digest_ctx *digest;
u_char *buf;
size_t buf_len;
};
size_t
ssh_hmac_bytes(int alg)
{
return ssh_digest_bytes(alg);
}
struct ssh_hmac_ctx *
ssh_hmac_start(int alg)
{
struct ssh_hmac_ctx *ret;
if ((ret = calloc(1, sizeof(*ret))) == NULL)
return NULL;
ret->alg = alg;
if ((ret->ictx = ssh_digest_start(alg)) == NULL ||
(ret->octx = ssh_digest_start(alg)) == NULL ||
(ret->digest = ssh_digest_start(alg)) == NULL)
goto fail;
ret->buf_len = ssh_digest_blocksize(ret->ictx);
if ((ret->buf = calloc(1, ret->buf_len)) == NULL)
goto fail;
return ret;
fail:
ssh_hmac_free(ret);
return NULL;
}
int
ssh_hmac_init(struct ssh_hmac_ctx *ctx, const void *key, size_t klen)
{
size_t i;
/* reset ictx and octx if no is key given */
if (key != NULL) {
/* truncate long keys */
if (klen <= ctx->buf_len)
memcpy(ctx->buf, key, klen);
else if (ssh_digest_memory(ctx->alg, key, klen, ctx->buf,
ctx->buf_len) < 0)
return -1;
for (i = 0; i < ctx->buf_len; i++)
ctx->buf[i] ^= 0x36;
if (ssh_digest_update(ctx->ictx, ctx->buf, ctx->buf_len) < 0)
return -1;
for (i = 0; i < ctx->buf_len; i++)
ctx->buf[i] ^= 0x36 ^ 0x5c;
if (ssh_digest_update(ctx->octx, ctx->buf, ctx->buf_len) < 0)
return -1;
explicit_bzero(ctx->buf, ctx->buf_len);
}
/* start with ictx */
if (ssh_digest_copy_state(ctx->ictx, ctx->digest) < 0)
return -1;
return 0;
}
int
ssh_hmac_update(struct ssh_hmac_ctx *ctx, const void *m, size_t mlen)
{
return ssh_digest_update(ctx->digest, m, mlen);
}
int
ssh_hmac_update_buffer(struct ssh_hmac_ctx *ctx, const Buffer *b)
{
return ssh_digest_update_buffer(ctx->digest, b);
}
int
ssh_hmac_final(struct ssh_hmac_ctx *ctx, u_char *d, size_t dlen)
{
size_t len;
len = ssh_digest_bytes(ctx->alg);
if (dlen < len ||
ssh_digest_final(ctx->digest, ctx->buf, len))
return -1;
/* switch to octx */
if (ssh_digest_copy_state(ctx->octx, ctx->digest) < 0 ||
ssh_digest_update(ctx->digest, ctx->buf, len) < 0 ||
ssh_digest_final(ctx->digest, d, dlen) < 0)
return -1;
return 0;
}
void
ssh_hmac_free(struct ssh_hmac_ctx *ctx)
{
if (ctx != NULL) {
ssh_digest_free(ctx->ictx);
ssh_digest_free(ctx->octx);
ssh_digest_free(ctx->digest);
if (ctx->buf) {
explicit_bzero(ctx->buf, ctx->buf_len);
free(ctx->buf);
}
explicit_bzero(ctx, sizeof(*ctx));
free(ctx);
}
}
#ifdef TEST
/* cc -DTEST hmac.c digest.c buffer.c cleanup.c fatal.c log.c xmalloc.c -lcrypto */
static void
hmac_test(void *key, size_t klen, void *m, size_t mlen, u_char *e, size_t elen)
{
struct ssh_hmac_ctx *ctx;
size_t i;
u_char digest[16];
if ((ctx = ssh_hmac_start(SSH_DIGEST_MD5)) == NULL)
printf("ssh_hmac_start failed");
if (ssh_hmac_init(ctx, key, klen) < 0 ||
ssh_hmac_update(ctx, m, mlen) < 0 ||
ssh_hmac_final(ctx, digest, sizeof(digest)) < 0)
printf("ssh_hmac_xxx failed");
ssh_hmac_free(ctx);
if (memcmp(e, digest, elen)) {
for (i = 0; i < elen; i++)
printf("[%zd] %2.2x %2.2x\n", i, e[i], digest[i]);
printf("mismatch\n");
} else
printf("ok\n");
}
int
main(int argc, char **argv)
{
/* try test vectors from RFC 2104 */
u_char key1[16] = {
0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb,
0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb };
u_char *data1 = "Hi There";
u_char dig1[16] = {
0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c,
0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d };
u_char *key2 = "Jefe";
u_char *data2 = "what do ya want for nothing?";
u_char dig2[16] = {
0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03,
0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38 };
u_char key3[16];
u_char data3[50];
u_char dig3[16] = {
0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88,
0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6 };
memset(key3, 0xaa, sizeof(key3));
memset(data3, 0xdd, sizeof(data3));
hmac_test(key1, sizeof(key1), data1, strlen(data1), dig1, sizeof(dig1));
hmac_test(key2, strlen(key2), data2, strlen(data2), dig2, sizeof(dig2));
hmac_test(key3, sizeof(key3), data3, sizeof(data3), dig3, sizeof(dig3));
return 0;
}
#endif

37
hmac.h Normal file
View File

@ -0,0 +1,37 @@
/* $OpenBSD: hmac.h,v 1.6 2014/01/27 18:58:14 markus Exp $ */
/*
* Copyright (c) 2014 Markus Friedl. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _HMAC_H
#define _HMAC_H
/* Returns the algorithm's digest length in bytes or 0 for invalid algorithm */
size_t ssh_hmac_bytes(int alg);
struct ssh_hmac_ctx;
struct ssh_hmac_ctx *ssh_hmac_start(int alg);
/* Sets the state of the HMAC or resets the state if key == NULL */
int ssh_hmac_init(struct ssh_hmac_ctx *ctx, const void *key, size_t klen)
__attribute__((__bounded__(__buffer__, 2, 3)));
int ssh_hmac_update(struct ssh_hmac_ctx *ctx, const void *m, size_t mlen)
__attribute__((__bounded__(__buffer__, 2, 3)));
int ssh_hmac_update_buffer(struct ssh_hmac_ctx *ctx, const Buffer *b);
int ssh_hmac_final(struct ssh_hmac_ctx *ctx, u_char *d, size_t dlen)
__attribute__((__bounded__(__buffer__, 2, 3)));
void ssh_hmac_free(struct ssh_hmac_ctx *ctx);
#endif /* _HMAC_H */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: hostfile.c,v 1.53 2014/01/09 23:20:00 djm Exp $ */
/* $OpenBSD: hostfile.c,v 1.54 2014/01/27 18:58:14 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -42,9 +42,6 @@
#include <netinet/in.h>
#include <openssl/hmac.h>
#include <openssl/sha.h>
#include <resolv.h>
#include <stdarg.h>
#include <stdio.h>
@ -58,6 +55,7 @@
#include "log.h"
#include "misc.h"
#include "digest.h"
#include "hmac.h"
struct hostkeys {
struct hostkey_entry *entries;
@ -102,9 +100,9 @@ extract_salt(const char *s, u_int l, u_char *salt, size_t salt_len)
debug2("extract_salt: salt decode error");
return (-1);
}
if (ret != SHA_DIGEST_LENGTH) {
debug2("extract_salt: expected salt len %d, got %d",
SHA_DIGEST_LENGTH, ret);
if (ret != (int)ssh_hmac_bytes(SSH_DIGEST_SHA1)) {
debug2("extract_salt: expected salt len %zd, got %d",
ssh_hmac_bytes(SSH_DIGEST_SHA1), ret);
return (-1);
}
@ -114,14 +112,13 @@ extract_salt(const char *s, u_int l, u_char *salt, size_t salt_len)
char *
host_hash(const char *host, const char *name_from_hostfile, u_int src_len)
{
const EVP_MD *md = EVP_sha1();
HMAC_CTX mac_ctx;
struct ssh_hmac_ctx *ctx;
u_char salt[256], result[256];
char uu_salt[512], uu_result[512];
static char encoded[1024];
u_int i, len;
len = EVP_MD_size(md);
len = ssh_digest_bytes(SSH_DIGEST_SHA1);
if (name_from_hostfile == NULL) {
/* Create new salt */
@ -134,14 +131,16 @@ host_hash(const char *host, const char *name_from_hostfile, u_int src_len)
return (NULL);
}
HMAC_Init(&mac_ctx, salt, len, md);
HMAC_Update(&mac_ctx, (u_char *)host, strlen(host));
HMAC_Final(&mac_ctx, result, NULL);
HMAC_cleanup(&mac_ctx);
if ((ctx = ssh_hmac_start(SSH_DIGEST_SHA1)) == NULL ||
ssh_hmac_init(ctx, salt, len) < 0 ||
ssh_hmac_update(ctx, host, strlen(host)) < 0 ||
ssh_hmac_final(ctx, result, sizeof(result)))
fatal("%s: ssh_hmac failed", __func__);
ssh_hmac_free(ctx);
if (__b64_ntop(salt, len, uu_salt, sizeof(uu_salt)) == -1 ||
__b64_ntop(result, len, uu_result, sizeof(uu_result)) == -1)
fatal("host_hash: __b64_ntop failed");
fatal("%s: __b64_ntop failed", __func__);
snprintf(encoded, sizeof(encoded), "%s%s%c%s", HASH_MAGIC, uu_salt,
HASH_DELIM, uu_result);

7
kex.h
View File

@ -1,4 +1,4 @@
/* $OpenBSD: kex.h,v 1.61 2014/01/25 10:12:50 dtucker Exp $ */
/* $OpenBSD: kex.h,v 1.62 2014/01/27 18:58:14 markus Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@ -105,9 +105,8 @@ struct Mac {
u_int key_len;
int type;
int etm; /* Encrypt-then-MAC */
const EVP_MD *evp_md;
HMAC_CTX evp_ctx;
struct umac_ctx *umac_ctx;
struct ssh_hmac_ctx *hmac_ctx;
struct umac_ctx *umac_ctx;
};
struct Comp {
int type;

85
mac.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: mac.c,v 1.26 2014/01/04 17:50:55 tedu Exp $ */
/* $OpenBSD: mac.c,v 1.27 2014/01/27 18:58:14 markus Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
*
@ -27,8 +27,6 @@
#include <sys/types.h>
#include <openssl/hmac.h>
#include <stdarg.h>
#include <string.h>
#include <signal.h>
@ -42,18 +40,20 @@
#include "mac.h"
#include "misc.h"
#include "digest.h"
#include "hmac.h"
#include "umac.h"
#include "openbsd-compat/openssl-compat.h"
#define SSH_EVP 1 /* OpenSSL EVP-based MAC */
#define SSH_DIGEST 1 /* SSH_DIGEST_XXX */
#define SSH_UMAC 2 /* UMAC (not integrated with OpenSSL) */
#define SSH_UMAC128 3
struct macalg {
char *name;
int type;
const EVP_MD * (*mdfunc)(void);
int alg;
int truncatebits; /* truncate digest if != 0 */
int key_len; /* just for UMAC */
int len; /* just for UMAC */
@ -62,33 +62,33 @@ struct macalg {
static const struct macalg macs[] = {
/* Encrypt-and-MAC (encrypt-and-authenticate) variants */
{ "hmac-sha1", SSH_EVP, EVP_sha1, 0, 0, 0, 0 },
{ "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, 0, 0, 0 },
{ "hmac-sha1", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 0 },
{ "hmac-sha1-96", SSH_DIGEST, SSH_DIGEST_SHA1, 96, 0, 0, 0 },
#ifdef HAVE_EVP_SHA256
{ "hmac-sha2-256", SSH_EVP, EVP_sha256, 0, 0, 0, 0 },
{ "hmac-sha2-512", SSH_EVP, EVP_sha512, 0, 0, 0, 0 },
{ "hmac-sha2-256", SSH_DIGEST, SSH_DIGEST_SHA256, 0, 0, 0, 0 },
{ "hmac-sha2-512", SSH_DIGEST, SSH_DIGEST_SHA512, 0, 0, 0, 0 },
#endif
{ "hmac-md5", SSH_EVP, EVP_md5, 0, 0, 0, 0 },
{ "hmac-md5-96", SSH_EVP, EVP_md5, 96, 0, 0, 0 },
{ "hmac-ripemd160", SSH_EVP, EVP_ripemd160, 0, 0, 0, 0 },
{ "hmac-ripemd160@openssh.com", SSH_EVP, EVP_ripemd160, 0, 0, 0, 0 },
{ "umac-64@openssh.com", SSH_UMAC, NULL, 0, 128, 64, 0 },
{ "umac-128@openssh.com", SSH_UMAC128, NULL, 0, 128, 128, 0 },
{ "hmac-md5", SSH_DIGEST, SSH_DIGEST_MD5, 0, 0, 0, 0 },
{ "hmac-md5-96", SSH_DIGEST, SSH_DIGEST_MD5, 96, 0, 0, 0 },
{ "hmac-ripemd160", SSH_DIGEST, SSH_DIGEST_RIPEMD160, 0, 0, 0, 0 },
{ "hmac-ripemd160@openssh.com", SSH_DIGEST, SSH_DIGEST_RIPEMD160, 0, 0, 0, 0 },
{ "umac-64@openssh.com", SSH_UMAC, 0, 0, 128, 64, 0 },
{ "umac-128@openssh.com", SSH_UMAC128, 0, 0, 128, 128, 0 },
/* Encrypt-then-MAC variants */
{ "hmac-sha1-etm@openssh.com", SSH_EVP, EVP_sha1, 0, 0, 0, 1 },
{ "hmac-sha1-96-etm@openssh.com", SSH_EVP, EVP_sha1, 96, 0, 0, 1 },
{ "hmac-sha1-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 1 },
{ "hmac-sha1-96-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA1, 96, 0, 0, 1 },
#ifdef HAVE_EVP_SHA256
{ "hmac-sha2-256-etm@openssh.com", SSH_EVP, EVP_sha256, 0, 0, 0, 1 },
{ "hmac-sha2-512-etm@openssh.com", SSH_EVP, EVP_sha512, 0, 0, 0, 1 },
{ "hmac-sha2-256-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA256, 0, 0, 0, 1 },
{ "hmac-sha2-512-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA512, 0, 0, 0, 1 },
#endif
{ "hmac-md5-etm@openssh.com", SSH_EVP, EVP_md5, 0, 0, 0, 1 },
{ "hmac-md5-96-etm@openssh.com", SSH_EVP, EVP_md5, 96, 0, 0, 1 },
{ "hmac-ripemd160-etm@openssh.com", SSH_EVP, EVP_ripemd160, 0, 0, 0, 1 },
{ "umac-64-etm@openssh.com", SSH_UMAC, NULL, 0, 128, 64, 1 },
{ "umac-128-etm@openssh.com", SSH_UMAC128, NULL, 0, 128, 128, 1 },
{ "hmac-md5-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_MD5, 0, 0, 0, 1 },
{ "hmac-md5-96-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_MD5, 96, 0, 0, 1 },
{ "hmac-ripemd160-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_RIPEMD160, 0, 0, 0, 1 },
{ "umac-64-etm@openssh.com", SSH_UMAC, 0, 0, 128, 64, 1 },
{ "umac-128-etm@openssh.com", SSH_UMAC128, 0, 0, 128, 128, 1 },
{ NULL, 0, NULL, 0, 0, 0, 0 }
{ NULL, 0, 0, 0, 0, 0, 0 }
};
/* Returns a list of supported MACs separated by the specified char. */
@ -113,14 +113,11 @@ mac_alg_list(char sep)
static void
mac_setup_by_alg(Mac *mac, const struct macalg *macalg)
{
int evp_len;
mac->type = macalg->type;
if (mac->type == SSH_EVP) {
mac->evp_md = macalg->mdfunc();
if ((evp_len = EVP_MD_size(mac->evp_md)) <= 0)
fatal("mac %s len %d", mac->name, evp_len);
mac->key_len = mac->mac_len = (u_int)evp_len;
if (mac->type == SSH_DIGEST) {
if ((mac->hmac_ctx = ssh_hmac_start(macalg->alg)) == NULL)
fatal("ssh_hmac_start(alg=%d) failed", macalg->alg);
mac->key_len = mac->mac_len = ssh_hmac_bytes(macalg->alg);
} else {
mac->mac_len = macalg->len / 8;
mac->key_len = macalg->key_len / 8;
@ -154,11 +151,10 @@ mac_init(Mac *mac)
if (mac->key == NULL)
fatal("mac_init: no key");
switch (mac->type) {
case SSH_EVP:
if (mac->evp_md == NULL)
case SSH_DIGEST:
if (mac->hmac_ctx == NULL ||
ssh_hmac_init(mac->hmac_ctx, mac->key, mac->key_len) < 0)
return -1;
HMAC_CTX_init(&mac->evp_ctx);
HMAC_Init(&mac->evp_ctx, mac->key, mac->key_len, mac->evp_md);
return 0;
case SSH_UMAC:
mac->umac_ctx = umac_new(mac->key);
@ -185,13 +181,14 @@ mac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen)
mac->mac_len, sizeof(u));
switch (mac->type) {
case SSH_EVP:
case SSH_DIGEST:
put_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, u.m, NULL);
if (ssh_hmac_init(mac->hmac_ctx, NULL, 0) < 0 ||
ssh_hmac_update(mac->hmac_ctx, b, sizeof(b)) < 0 ||
ssh_hmac_update(mac->hmac_ctx, data, datalen) < 0 ||
ssh_hmac_final(mac->hmac_ctx, u.m, sizeof(u.m)) < 0)
fatal("ssh_hmac failed");
break;
case SSH_UMAC:
put_u64(nonce, seqno);
@ -218,9 +215,9 @@ mac_clear(Mac *mac)
} else if (mac->type == SSH_UMAC128) {
if (mac->umac_ctx != NULL)
umac128_delete(mac->umac_ctx);
} else if (mac->evp_md != NULL)
HMAC_cleanup(&mac->evp_ctx);
mac->evp_md = NULL;
} else if (mac->hmac_ctx != NULL)
ssh_hmac_free(mac->hmac_ctx);
mac->hmac_ctx = NULL;
mac->umac_ctx = NULL;
}