Skip to content

Commit

Permalink
- [email protected] 2014/01/27 18:58:14
Browse files Browse the repository at this point in the history
     [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@
  • Loading branch information
djmdjm committed Feb 4, 2014
1 parent 69d0d09 commit 4e8d937
Show file tree
Hide file tree
Showing 9 changed files with 332 additions and 71 deletions.
7 changes: 7 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
20140204
- OpenBSD CVS Sync
- [email protected] 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.
Expand Down
4 changes: 2 additions & 2 deletions Makefile.in
Original file line number Diff line number Diff line change
@@ -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@
Expand Down Expand Up @@ -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 \
Expand Down
25 changes: 21 additions & 4 deletions digest.c
Original file line number Diff line number Diff line change
@@ -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 <[email protected]>
*
Expand Down Expand Up @@ -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)
{
Expand All @@ -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)
{
Expand Down Expand Up @@ -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
Expand Down
12 changes: 10 additions & 2 deletions digest.h
Original file line number Diff line number Diff line change
@@ -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 <[email protected]>
*
Expand Down Expand Up @@ -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)
Expand All @@ -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)));
Expand Down
197 changes: 197 additions & 0 deletions hmac.c
Original file line number Diff line number Diff line change
@@ -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 changes: 37 additions & 0 deletions hmac.h
Original file line number Diff line number Diff line change
@@ -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 */
Loading

0 comments on commit 4e8d937

Please sign in to comment.