mirror of git://anongit.mindrot.org/openssh.git
- 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@
This commit is contained in:
parent
69d0d09f76
commit
4e8d937af7
|
@ -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.
|
||||
|
|
|
@ -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 \
|
||||
|
|
25
digest.c
25
digest.c
|
@ -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
|
||||
|
|
12
digest.h
12
digest.h
|
@ -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)));
|
||||
|
|
|
@ -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
|
|
@ -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 */
|
29
hostfile.c
29
hostfile.c
|
@ -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
7
kex.h
|
@ -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
85
mac.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue