Import sha256 from libcperciva

Import md2, md4, sha384 and sha512 from XySSL
This commit is contained in:
Dag-Erling Smørgrav 2014-07-10 14:51:07 +00:00 committed by des
parent 0d22f2f203
commit 593125c353
22 changed files with 4056 additions and 29 deletions

View file

@ -10,6 +10,8 @@ cryb_HEADERS = \
hmac.h \
hotp.h \
mac.h \
md2.h \
md4.h \
md5.h \
oath.h \
oath_constants.h \
@ -18,6 +20,9 @@ cryb_HEADERS = \
rfc3986.h \
rfc4648.h \
sha1.h \
sha256.h \
sha384.h \
sha512.h \
to.h \
totp.h \
version.h

141
include/cryb/md2.h Normal file
View file

@ -0,0 +1,141 @@
/*
* Copyright (c) 2006-2007 Christophe Devine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Cryb$
*/
#ifndef CRYB_MD2_H_INCLUDED
#define CRYB_MD2_H_INCLUDED
#define MD2_DIGEST_LEN 16
#define md2_digest cryb_md2_digest
#define md2_ctx cryb_md2_ctx
#define md2_init cryb_md2_init
#define md2_update cryb_md2_update
#define md2_final cryb_md2_final
#define md2_complete cryb_md2_complete
extern struct digest_algorithm md2_digest;
/**
* \brief MD2 context structure
*/
typedef struct
{
unsigned char cksum[16]; /*!< checksum of the data block */
unsigned char state[48]; /*!< intermediate digest state */
unsigned char buffer[16]; /*!< data block being processed */
unsigned char ipad[64]; /*!< HMAC: inner padding */
unsigned char opad[64]; /*!< HMAC: outer padding */
int left; /*!< amount of data in buffer */
}
md2_ctx;
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief MD2 context setup
*
* \param ctx context to be initialized
*/
void md2_init( md2_ctx *ctx );
/**
* \brief MD2 process buffer
*
* \param ctx MD2 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void md2_update( md2_ctx *ctx, const void *input, int ilen );
/**
* \brief MD2 final digest
*
* \param ctx MD2 context
* \param output MD2 checksum result
*/
void md2_final( md2_ctx *ctx, unsigned char output[16] );
/**
* \brief Output = MD2( input buffer )
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output MD2 checksum result
*/
void md2_complete( const void *input, int ilen, unsigned char output[16] );
/**
* \brief MD2 HMAC context setup
*
* \param ctx HMAC context to be initialized
* \param key HMAC secret key
* \param keylen length of the HMAC key
*/
void md2_hmac_init( md2_ctx *ctx, unsigned char *key, int keylen );
/**
* \brief MD2 HMAC process buffer
*
* \param ctx HMAC context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void md2_hmac_update( md2_ctx *ctx, unsigned char *input, int ilen );
/**
* \brief MD2 HMAC final digest
*
* \param ctx HMAC context
* \param output MD2 HMAC checksum result
*/
void md2_hmac_final( md2_ctx *ctx, unsigned char output[16] );
/**
* \brief Output = HMAC-MD2( hmac key, input buffer )
*
* \param key HMAC secret key
* \param keylen length of the HMAC key
* \param input buffer holding the data
* \param ilen length of the input data
* \param output HMAC-MD2 result
*/
void md2_hmac_complete( unsigned char *key, int keylen,
unsigned char *input, int ilen,
unsigned char output[16] );
#ifdef __cplusplus
}
#endif
#endif /* md2.h */

140
include/cryb/md4.h Normal file
View file

@ -0,0 +1,140 @@
/*
* Copyright (c) 2006-2007 Christophe Devine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Cryb$
*/
#ifndef CRYB_MD4_H_INCLUDED
#define CRYB_MD4_H_INCLUDED
#define MD4_DIGEST_LEN 16
#define md4_digest cryb_md4_digest
#define md4_ctx cryb_md4_ctx
#define md4_init cryb_md4_init
#define md4_update cryb_md4_update
#define md4_final cryb_md4_final
#define md4_complete cryb_md4_complete
extern struct digest_algorithm md4_digest;
/**
* \brief MD4 context structure
*/
typedef struct
{
unsigned long total[2]; /*!< number of bytes processed */
unsigned long state[4]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
unsigned char ipad[64]; /*!< HMAC: inner padding */
unsigned char opad[64]; /*!< HMAC: outer padding */
}
md4_ctx;
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief MD4 context setup
*
* \param ctx context to be initialized
*/
void md4_init( md4_ctx *ctx );
/**
* \brief MD4 process buffer
*
* \param ctx MD4 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void md4_update( md4_ctx *ctx, const void *input, int ilen );
/**
* \brief MD4 final digest
*
* \param ctx MD4 context
* \param output MD4 checksum result
*/
void md4_final( md4_ctx *ctx, unsigned char output[16] );
/**
* \brief Output = MD4( input buffer )
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output MD4 checksum result
*/
void md4_complete( const void *input, int ilen, unsigned char output[16] );
/**
* \brief MD4 HMAC context setup
*
* \param ctx HMAC context to be initialized
* \param key HMAC secret key
* \param keylen length of the HMAC key
*/
void md4_hmac_init( md4_ctx *ctx, unsigned char *key, int keylen );
/**
* \brief MD4 HMAC process buffer
*
* \param ctx HMAC context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void md4_hmac_update( md4_ctx *ctx, unsigned char *input, int ilen );
/**
* \brief MD4 HMAC final digest
*
* \param ctx HMAC context
* \param output MD4 HMAC checksum result
*/
void md4_hmac_final( md4_ctx *ctx, unsigned char output[16] );
/**
* \brief Output = HMAC-MD4( hmac key, input buffer )
*
* \param key HMAC secret key
* \param keylen length of the HMAC key
* \param input buffer holding the data
* \param ilen length of the input data
* \param output HMAC-MD4 result
*/
void md4_hmac_complete( unsigned char *key, int keylen,
unsigned char *input, int ilen,
unsigned char output[16] );
#ifdef __cplusplus
}
#endif
#endif

View file

@ -38,14 +38,14 @@
#define MD5_DIGEST_LEN 16
#define md5_algorithm cryb_md5_algorithm
#define md5_digest cryb_md5_digest
#define md5_ctx cryb_md5_ctx
#define md5_init cryb_md5_init
#define md5_update cryb_md5_update
#define md5_final cryb_md5_final
#define md5_complete cryb_md5_complete
extern struct digest_algorithm md5_algorithm;
extern struct digest_algorithm md5_digest;
typedef struct md5_ctx {
uint8_t block[64];

View file

@ -38,14 +38,14 @@
#define SHA1_DIGEST_LEN 20
#define sha1_algorithm cryb_sha1_algorithm
#define sha1_digest cryb_sha1_digest
#define sha1_ctx cryb_sha1_ctx
#define sha1_init cryb_sha1_init
#define sha1_update cryb_sha1_update
#define sha1_final cryb_sha1_final
#define sha1_complete cryb_sha1_complete
extern struct digest_algorithm sha1_algorithm;
extern struct digest_algorithm sha1_digest;
typedef struct sha1_ctx {
uint8_t block[64];

126
include/cryb/sha256.h Normal file
View file

@ -0,0 +1,126 @@
/*-
* Copyright (c) 2005-2013 Colin Percival
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Cryb$
*/
#ifndef CRYB_SHA256_H_INCLUDED
#define CRYB_SHA256_H_INCLUDED
#define SHA256_DIGEST_LEN 32
/*
* Use #defines in order to avoid namespace collisions with anyone else's
* SHA256 code (e.g., the code in OpenSSL).
*/
#define sha256_digest cryb_sha256_digest
#define sha256_ctx cryb_sha256_ctx
#define sha256_init cryb_sha256_init
#define sha256_update cryb_sha256_update
#define sha256_final cryb_sha256_final
#define sha256_complete cryb_sha256_complete
extern struct digest_algorithm sha256_digest;
#define hmac_sha256_init cryb_hmac_sha256_init
#define hmac_sha256_update cryb_hmac_sha256_update
#define hmac_sha256_final cryb_hmac_sha256_final
#define hmac_sha256_complete cryb_hmac_sha256_complete
#define hmac_sha256_ctx cryb_hmac_sha256_ctx
/* Context structure for SHA256 operations. */
typedef struct {
uint32_t state[8];
uint64_t count;
uint8_t buf[64];
} sha256_ctx;
/**
* sha256_init(ctx):
* Initialize the SHA256 context ${ctx}.
*/
void sha256_init(sha256_ctx *);
/**
* sha256_update(ctx, in, len):
* Input ${len} bytes from ${in} into the SHA256 context ${ctx}.
*/
void sha256_update(sha256_ctx *, const void *, size_t);
/**
* sha256_final(ctx, digest):
* Output the SHA256 hash of the data input to the context ${ctx} into the
* buffer ${digest}.
*/
void sha256_final(sha256_ctx *, uint8_t[SHA256_DIGEST_LEN]);
/**
* sha256_complete(in, len, digest):
* Compute the SHA256 hash of ${len} bytes from $in} and write it to ${digest}.
*/
void sha256_complete(const void *, size_t, uint8_t[SHA256_DIGEST_LEN]);
/* Context structure for HMAC-SHA256 operations. */
typedef struct {
sha256_ctx ictx;
sha256_ctx octx;
} hmac_sha256_ctx;
/**
* hmac_sha256_init(ctx, K, Klen):
* Initialize the HMAC-SHA256 context ${ctx} with ${Klen} bytes of key from
* ${K}.
*/
void hmac_sha256_init(hmac_sha256_ctx *, const void *, size_t);
/**
* hmac_sha256_update(ctx, in, len):
* Input ${len} bytes from ${in} into the HMAC-SHA256 context ${ctx}.
*/
void hmac_sha256_update(hmac_sha256_ctx *, const void *, size_t);
/**
* hmac_sha256_final(ctx, digest):
* Output the HMAC-SHA256 of the data input to the context ${ctx} into the
* buffer ${digest}.
*/
void hmac_sha256_final(hmac_sha256_ctx *, uint8_t[SHA256_DIGEST_LEN]);
/**
* hmac_sha256_complete(K, Klen, in, len, digest):
* Compute the HMAC-SHA256 of ${len} bytes from ${in} using the key ${K} of
* length ${Klen}, and write the result to ${digest}.
*/
void hmac_sha256_complete(const void *, size_t, const void *, size_t, uint8_t[32]);
/**
* PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
* Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
* write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
*/
void pbkdf2_sha256(const uint8_t *, size_t, const uint8_t *, size_t,
uint64_t, uint8_t *, size_t);
#endif

141
include/cryb/sha384.h Normal file
View file

@ -0,0 +1,141 @@
/*
* Copyright (c) 2006-2007 Christophe Devine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Cryb$
*/
#ifndef CRYB_SHA384_H_INCLUDED
#define CRYB_SHA384_H_INCLUDED
#define SHA384_DIGEST_LEN 48
#define sha384_digest cryb_sha384_digest
#define sha384_ctx cryb_sha384_ctx
#define sha384_init cryb_sha384_init
#define sha384_update cryb_sha384_update
#define sha384_final cryb_sha384_final
#define sha384_complete cryb_sha384_complete
extern struct digest_algorithm sha384_digest;
/**
* \brief SHA-384 context structure
*/
typedef struct
{
uint64_t total[2]; /*!< number of bytes processed */
uint64_t state[8]; /*!< intermediate digest state */
uint8_t buffer[128]; /*!< data block being processed */
uint8_t ipad[128]; /*!< HMAC: inner padding */
uint8_t opad[128]; /*!< HMAC: outer padding */
}
sha384_ctx;
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief SHA-384 context setup
*
* \param ctx context to be initialized
*/
void sha384_init( sha384_ctx *ctx );
/**
* \brief SHA-384 process buffer
*
* \param ctx SHA-384 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void sha384_update( sha384_ctx *ctx, const void *input, int ilen );
/**
* \brief SHA-384 final digest
*
* \param ctx SHA-384 context
* \param output SHA-384/384 checksum result
*/
void sha384_final( sha384_ctx *ctx, unsigned char output[64] );
/**
* \brief Output = SHA-384( input buffer )
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output SHA-384/384 checksum result
*/
void sha384_complete( const void *input, int ilen,
unsigned char output[64] );
/**
* \brief SHA-384 HMAC context setup
*
* \param ctx HMAC context to be initialized
* \param key HMAC secret key
* \param keylen length of the HMAC key
*/
void sha384_hmac_init( sha384_ctx *ctx, unsigned char *key, int keylen );
/**
* \brief SHA-384 HMAC process buffer
*
* \param ctx HMAC context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void sha384_hmac_update( sha384_ctx *ctx, unsigned char *input, int ilen );
/**
* \brief SHA-384 HMAC final digest
*
* \param ctx HMAC context
* \param output SHA-384/384 HMAC checksum result
*/
void sha384_hmac_final( sha384_ctx *ctx, unsigned char output[64] );
/**
* \brief Output = HMAC-SHA-384( hmac key, input buffer )
*
* \param key HMAC secret key
* \param keylen length of the HMAC key
* \param input buffer holding the data
* \param ilen length of the input data
* \param output HMAC-SHA-384/384 result
*/
void sha384_hmac_complete( unsigned char *key, int keylen,
unsigned char *input, int ilen,
unsigned char output[64] );
#ifdef __cplusplus
}
#endif
#endif

141
include/cryb/sha512.h Normal file
View file

@ -0,0 +1,141 @@
/*
* Copyright (c) 2006-2007 Christophe Devine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Cryb$
*/
#ifndef CRYB_SHA512_H_INCLUDED
#define CRYB_SHA512_H_INCLUDED
#define SHA512_DIGEST_LEN 64
#define sha512_digest cryb_sha512_digest
#define sha512_ctx cryb_sha512_ctx
#define sha512_init cryb_sha512_init
#define sha512_update cryb_sha512_update
#define sha512_final cryb_sha512_final
#define sha512_complete cryb_sha512_complete
extern struct digest_algorithm sha512_digest;
/**
* \brief SHA-512 context structure
*/
typedef struct
{
uint64_t total[2]; /*!< number of bytes processed */
uint64_t state[8]; /*!< intermediate digest state */
uint8_t buffer[128]; /*!< data block being processed */
uint8_t ipad[128]; /*!< HMAC: inner padding */
uint8_t opad[128]; /*!< HMAC: outer padding */
}
sha512_ctx;
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief SHA-512 context setup
*
* \param ctx context to be initialized
*/
void sha512_init( sha512_ctx *ctx );
/**
* \brief SHA-512 process buffer
*
* \param ctx SHA-512 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void sha512_update( sha512_ctx *ctx, const void *input, int ilen );
/**
* \brief SHA-512 final digest
*
* \param ctx SHA-512 context
* \param output SHA-384/512 checksum result
*/
void sha512_final( sha512_ctx *ctx, unsigned char output[64] );
/**
* \brief Output = SHA-512( input buffer )
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output SHA-384/512 checksum result
*/
void sha512_complete( const void *input, int ilen,
unsigned char output[64] );
/**
* \brief SHA-512 HMAC context setup
*
* \param ctx HMAC context to be initialized
* \param key HMAC secret key
* \param keylen length of the HMAC key
*/
void sha512_hmac_init( sha512_ctx *ctx, unsigned char *key, int keylen );
/**
* \brief SHA-512 HMAC process buffer
*
* \param ctx HMAC context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void sha512_hmac_update( sha512_ctx *ctx, unsigned char *input, int ilen );
/**
* \brief SHA-512 HMAC final digest
*
* \param ctx HMAC context
* \param output SHA-384/512 HMAC checksum result
*/
void sha512_hmac_final( sha512_ctx *ctx, unsigned char output[64] );
/**
* \brief Output = HMAC-SHA-512( hmac key, input buffer )
*
* \param key HMAC secret key
* \param keylen length of the HMAC key
* \param input buffer holding the data
* \param ilen length of the input data
* \param output HMAC-SHA-384/512 result
*/
void sha512_hmac_complete( unsigned char *key, int keylen,
unsigned char *input, int ilen,
unsigned char output[64] );
#ifdef __cplusplus
}
#endif
#endif

View file

@ -5,5 +5,10 @@ AM_CPPFLAGS = -I$(top_srcdir)/include
lib_LTLIBRARIES = libcryb-digest.la
libcryb_digest_la_SOURCES = \
md2.c \
md4.c \
md5.c \
sha1.c
sha1.c \
sha256.c \
sha384.c \
sha512.c

257
lib/digest/md2.c Normal file
View file

@ -0,0 +1,257 @@
/*
* Copyright (c) 2006-2007 Christophe Devine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Cryb$
*/
/*
* The MD2 algorithm was designed by Ron Rivest in 1989.
*
* http://www.ietf.org/rfc/rfc1115.txt
* http://www.ietf.org/rfc/rfc1319.txt
*/
#include "cryb/impl.h"
#include <string.h>
#include <cryb/digest.h>
#include <cryb/md2.h>
static const unsigned char PI_SUBST[256] =
{
0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36,
0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3,
0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C,
0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16,
0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E,
0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E,
0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2,
0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E,
0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3,
0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56,
0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6,
0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D,
0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65,
0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0,
0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C,
0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E,
0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81,
0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA,
0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88,
0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE,
0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58,
0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99,
0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14
};
/*
* MD2 context setup
*/
void md2_init( md2_ctx *ctx )
{
memset( ctx, 0, sizeof( md2_ctx ) );
}
static void md2_process( md2_ctx *ctx )
{
int i, j;
unsigned char t = 0;
for( i = 0; i < 16; i++ )
{
ctx->state[i + 16] = ctx->buffer[i];
ctx->state[i + 32] =
(unsigned char)( ctx->buffer[i] ^ ctx->state[i]);
}
for( i = 0; i < 18; i++ )
{
for( j = 0; j < 48; j++ )
{
ctx->state[j] = (unsigned char)
( ctx->state[j] ^ PI_SUBST[t] );
t = ctx->state[j];
}
t = (unsigned char)( t + i );
}
t = ctx->cksum[15];
for( i = 0; i < 16; i++ )
{
ctx->cksum[i] = (unsigned char)
( ctx->cksum[i] ^ PI_SUBST[ctx->buffer[i] ^ t] );
t = ctx->cksum[i];
}
}
/*
* MD2 process buffer
*/
void md2_update( md2_ctx *ctx, const void *input, int ilen )
{
int fill;
while( ilen > 0 )
{
if( ctx->left + ilen > 16 )
fill = 16 - ctx->left;
else
fill = ilen;
memcpy( ctx->buffer + ctx->left, input, fill );
ctx->left += fill;
input += fill;
ilen -= fill;
if( ctx->left == 16 )
{
ctx->left = 0;
md2_process( ctx );
}
}
}
/*
* MD2 final digest
*/
void md2_final( md2_ctx *ctx, unsigned char *output )
{
int i;
unsigned char x;
x = (unsigned char)( 16 - ctx->left );
for( i = ctx->left; i < 16; i++ )
ctx->buffer[i] = x;
md2_process( ctx );
memcpy( ctx->buffer, ctx->cksum, sizeof ctx->cksum );
md2_process( ctx );
memcpy( output, ctx->state, MD2_DIGEST_LEN );
}
/*
* output = MD2( input buffer )
*/
void md2_complete( const void *input, int ilen, unsigned char *output )
{
md2_ctx ctx;
md2_init( &ctx );
md2_update( &ctx, input, ilen );
md2_final( &ctx, output );
memset( &ctx, 0, sizeof( md2_ctx ) );
}
/*
* MD2 HMAC context setup
*/
void md2_hmac_init( md2_ctx *ctx, unsigned char *key, int keylen )
{
int i;
unsigned char sum[MD2_DIGEST_LEN];
if( keylen > 64 )
{
md2_complete( key, keylen, sum );
keylen = sizeof sum;
key = sum;
}
memset( ctx->ipad, 0x36, sizeof ctx->ipad );
memset( ctx->opad, 0x5C, sizeof ctx->opad );
for( i = 0; i < keylen; i++ )
{
ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
}
md2_init( ctx );
md2_update( ctx, ctx->ipad, sizeof ctx->ipad );
memset( sum, 0, sizeof( sum ) );
}
/*
* MD2 HMAC process buffer
*/
void md2_hmac_update( md2_ctx *ctx, unsigned char *input, int ilen )
{
md2_update( ctx, input, ilen );
}
/*
* MD2 HMAC final digest
*/
void md2_hmac_final( md2_ctx *ctx, unsigned char *output )
{
unsigned char tmpbuf[MD2_DIGEST_LEN];
md2_final( ctx, tmpbuf );
md2_init( ctx );
md2_update( ctx, ctx->opad, sizeof ctx->opad );
md2_update( ctx, tmpbuf, sizeof tmpbuf );
md2_final( ctx, output );
memset( tmpbuf, 0, sizeof( tmpbuf ) );
}
/*
* output = HMAC-MD2( hmac key, input buffer )
*/
void md2_hmac_complete( unsigned char *key, int keylen, unsigned char *input, int ilen,
unsigned char *output )
{
md2_ctx ctx;
md2_hmac_init( &ctx, key, keylen );
md2_hmac_update( &ctx, input, ilen );
md2_hmac_final( &ctx, output );
memset( &ctx, 0, sizeof( md2_ctx ) );
}
struct digest_algorithm md2_digest = {
.name = "md2",
.contextlen = sizeof md2_digest,
.digestlen = MD2_DIGEST_LEN,
.init = (digest_init_func)md2_init,
.update = (digest_update_func)md2_update,
.final = (digest_final_func)md2_final,
.complete = (digest_complete_func)md2_complete,
};

356
lib/digest/md4.c Normal file
View file

@ -0,0 +1,356 @@
/*
* Copyright (c) 2006-2007 Christophe Devine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Cryb$
*/
/*
* The MD4 algorithm was designed by Ron Rivest in 1990.
*
* http://www.ietf.org/rfc/rfc1186.txt
* http://www.ietf.org/rfc/rfc1320.txt
*/
#include "cryb/impl.h"
#include <string.h>
#include <cryb/digest.h>
#include <cryb/md4.h>
/*
* 32-bit integer manipulation macros (little endian)
*/
#ifndef GET_ULONG_LE
#define GET_ULONG_LE(n,b,i) \
do { \
(n) = ( (unsigned long) (b)[(i) ] ) \
| ( (unsigned long) (b)[(i) + 1] << 8 ) \
| ( (unsigned long) (b)[(i) + 2] << 16 ) \
| ( (unsigned long) (b)[(i) + 3] << 24 ); \
} while (0)
#endif
#ifndef PUT_ULONG_LE
#define PUT_ULONG_LE(n,b,i) \
do { \
(b)[(i) ] = (unsigned char) ( (n) ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
} while (0)
#endif
/*
* MD4 context setup
*/
void md4_init( md4_ctx *ctx )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
}
static void md4_process( md4_ctx *ctx, const unsigned char *data )
{
unsigned long X[16], A, B, C, D;
GET_ULONG_LE( X[ 0], data, 0 );
GET_ULONG_LE( X[ 1], data, 4 );
GET_ULONG_LE( X[ 2], data, 8 );
GET_ULONG_LE( X[ 3], data, 12 );
GET_ULONG_LE( X[ 4], data, 16 );
GET_ULONG_LE( X[ 5], data, 20 );
GET_ULONG_LE( X[ 6], data, 24 );
GET_ULONG_LE( X[ 7], data, 28 );
GET_ULONG_LE( X[ 8], data, 32 );
GET_ULONG_LE( X[ 9], data, 36 );
GET_ULONG_LE( X[10], data, 40 );
GET_ULONG_LE( X[11], data, 44 );
GET_ULONG_LE( X[12], data, 48 );
GET_ULONG_LE( X[13], data, 52 );
GET_ULONG_LE( X[14], data, 56 );
GET_ULONG_LE( X[15], data, 60 );
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
#define F(x, y, z) ((x & y) | ((~x) & z))
#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
P( A, B, C, D, X[ 0], 3 );
P( D, A, B, C, X[ 1], 7 );
P( C, D, A, B, X[ 2], 11 );
P( B, C, D, A, X[ 3], 19 );
P( A, B, C, D, X[ 4], 3 );
P( D, A, B, C, X[ 5], 7 );
P( C, D, A, B, X[ 6], 11 );
P( B, C, D, A, X[ 7], 19 );
P( A, B, C, D, X[ 8], 3 );
P( D, A, B, C, X[ 9], 7 );
P( C, D, A, B, X[10], 11 );
P( B, C, D, A, X[11], 19 );
P( A, B, C, D, X[12], 3 );
P( D, A, B, C, X[13], 7 );
P( C, D, A, B, X[14], 11 );
P( B, C, D, A, X[15], 19 );
#undef P
#undef F
#define F(x,y,z) ((x & y) | (x & z) | (y & z))
#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
P( A, B, C, D, X[ 0], 3 );
P( D, A, B, C, X[ 4], 5 );
P( C, D, A, B, X[ 8], 9 );
P( B, C, D, A, X[12], 13 );
P( A, B, C, D, X[ 1], 3 );
P( D, A, B, C, X[ 5], 5 );
P( C, D, A, B, X[ 9], 9 );
P( B, C, D, A, X[13], 13 );
P( A, B, C, D, X[ 2], 3 );
P( D, A, B, C, X[ 6], 5 );
P( C, D, A, B, X[10], 9 );
P( B, C, D, A, X[14], 13 );
P( A, B, C, D, X[ 3], 3 );
P( D, A, B, C, X[ 7], 5 );
P( C, D, A, B, X[11], 9 );
P( B, C, D, A, X[15], 13 );
#undef P
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
P( A, B, C, D, X[ 0], 3 );
P( D, A, B, C, X[ 8], 9 );
P( C, D, A, B, X[ 4], 11 );
P( B, C, D, A, X[12], 15 );
P( A, B, C, D, X[ 2], 3 );
P( D, A, B, C, X[10], 9 );
P( C, D, A, B, X[ 6], 11 );
P( B, C, D, A, X[14], 15 );
P( A, B, C, D, X[ 1], 3 );
P( D, A, B, C, X[ 9], 9 );
P( C, D, A, B, X[ 5], 11 );
P( B, C, D, A, X[13], 15 );
P( A, B, C, D, X[ 3], 3 );
P( D, A, B, C, X[11], 9 );
P( C, D, A, B, X[ 7], 11 );
P( B, C, D, A, X[15], 15 );
#undef F
#undef P
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
}
/*
* MD4 process buffer
*/
void md4_update( md4_ctx *ctx, const void *input, int ilen )
{
int fill;
unsigned long left;
if( ilen <= 0 )
return;
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += ilen;
ctx->total[0] &= 0xFFFFFFFF;
if( ctx->total[0] < (unsigned long) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, fill );
md4_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 )
{
md4_process( ctx, input );
input += 64;
ilen -= 64;
}
if( ilen > 0 )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, ilen );
}
}
static const unsigned char md4_padding[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* MD4 final digest
*/
void md4_final( md4_ctx *ctx, unsigned char *output )
{
unsigned long last, padn;
unsigned long high, low;
unsigned char msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_ULONG_LE( low, msglen, 0 );
PUT_ULONG_LE( high, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
md4_update( ctx, md4_padding, padn );
md4_update( ctx, msglen, 8 );
PUT_ULONG_LE( ctx->state[0], output, 0 );
PUT_ULONG_LE( ctx->state[1], output, 4 );
PUT_ULONG_LE( ctx->state[2], output, 8 );
PUT_ULONG_LE( ctx->state[3], output, 12 );
}
/*
* output = MD4( input buffer )
*/
void md4_complete( const void *input, int ilen, unsigned char *output )
{
md4_ctx ctx;
md4_init( &ctx );
md4_update( &ctx, input, ilen );
md4_final( &ctx, output );
memset( &ctx, 0, sizeof( md4_ctx ) );
}
/*
* MD4 HMAC context setup
*/
void md4_hmac_init( md4_ctx *ctx, unsigned char *key, int keylen )
{
int i;
unsigned char sum[16];
if( keylen > 64 )
{
md4_complete( key, keylen, sum );
keylen = 16;
key = sum;
}
memset( ctx->ipad, 0x36, 64 );
memset( ctx->opad, 0x5C, 64 );
for( i = 0; i < keylen; i++ )
{
ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
}
md4_init( ctx );
md4_update( ctx, ctx->ipad, 64 );
memset( sum, 0, sizeof( sum ) );
}
/*
* MD4 HMAC process buffer
*/
void md4_hmac_update( md4_ctx *ctx, unsigned char *input, int ilen )
{
md4_update( ctx, input, ilen );
}
/*
* MD4 HMAC final digest
*/
void md4_hmac_final( md4_ctx *ctx, unsigned char *output )
{
unsigned char tmpbuf[MD4_DIGEST_LEN];
md4_final( ctx, tmpbuf );
md4_init( ctx );
md4_update( ctx, ctx->opad, 64 );
md4_update( ctx, tmpbuf, 16 );
md4_final( ctx, output );
memset( tmpbuf, 0, sizeof( tmpbuf ) );
}
/*
* output = HMAC-MD4( hmac key, input buffer )
*/
void md4_hmac_complete( unsigned char *key, int keylen, unsigned char *input, int ilen,
unsigned char output[16] )
{
md4_ctx ctx;
md4_hmac_init( &ctx, key, keylen );
md4_hmac_update( &ctx, input, ilen );
md4_hmac_final( &ctx, output );
memset( &ctx, 0, sizeof( md4_ctx ) );
}
struct digest_algorithm md4_digest = {
.name = "md4",
.contextlen = sizeof md4_digest,
.digestlen = MD4_DIGEST_LEN,
.init = (digest_init_func)md4_init,
.update = (digest_update_func)md4_update,
.final = (digest_final_func)md4_final,
.complete = (digest_complete_func)md4_complete,
};

View file

@ -35,10 +35,6 @@
#include "cryb/impl.h"
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_SYS_ENDIAN_H
#include <sys/endian.h>
#endif
@ -48,6 +44,9 @@
#include <endian.h>
#endif
#include <stdint.h>
#include <string.h>
#include <cryb/digest.h>
#include <cryb/bitwise.h>
#include <cryb/md5.h>
@ -209,19 +208,19 @@ md5_update(struct md5_ctx *ctx, const void *buf, size_t len)
size_t copylen;
while (len) {
if (ctx->blocklen > 0 || len < 64) {
copylen = 64 - ctx->blocklen;
if (ctx->blocklen > 0 || len < sizeof ctx->block) {
copylen = sizeof ctx->block - ctx->blocklen;
if (copylen > len)
copylen = len;
memcpy(ctx->block + ctx->blocklen, buf, copylen);
ctx->blocklen += copylen;
if (ctx->blocklen == 64) {
if (ctx->blocklen == sizeof ctx->block) {
md5_compute(ctx, ctx->block);
ctx->blocklen = 0;
memset(ctx->block, 0, 64);
memset(ctx->block, 0, sizeof ctx->block);
}
} else {
copylen = 64;
copylen = sizeof ctx->block;
md5_compute(ctx, buf);
}
ctx->bitlen += copylen * 8;
@ -238,7 +237,7 @@ md5_final(struct md5_ctx *ctx, void *digest)
if (ctx->blocklen > 56) {
md5_compute(ctx, ctx->block);
ctx->blocklen = 0;
memset(ctx->block, 0, 64);
memset(ctx->block, 0, sizeof ctx->block);
}
le32enc(ctx->block + 56, ctx->bitlen & 0xffffffffUL);
le32enc(ctx->block + 60, ctx->bitlen >> 32);

View file

@ -35,10 +35,6 @@
#include "cryb/impl.h"
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_SYS_ENDIAN_H
#include <sys/endian.h>
#endif
@ -48,6 +44,9 @@
#include <endian.h>
#endif
#include <stdint.h>
#include <string.h>
#include <cryb/digest.h>
#include <cryb/bitwise.h>
@ -119,19 +118,19 @@ sha1_update(struct sha1_ctx *ctx, const void *buf, size_t len)
size_t copylen;
while (len) {
if (ctx->blocklen > 0 || len < 64) {
if (ctx->blocklen > 0 || len < sizeof ctx->block) {
copylen = sizeof ctx->block - ctx->blocklen;
if (copylen > len)
copylen = len;
memcpy(ctx->block + ctx->blocklen, buf, copylen);
ctx->blocklen += copylen;
if (ctx->blocklen == 64) {
if (ctx->blocklen == sizeof ctx->block) {
sha1_compute(ctx, ctx->block);
ctx->blocklen = 0;
memset(ctx->block, 0, 64);
memset(ctx->block, 0, sizeof ctx->block);
}
} else {
copylen = 64;
copylen = sizeof ctx->block;
sha1_compute(ctx, buf);
}
ctx->bitlen += copylen * 8;
@ -149,7 +148,7 @@ sha1_final(struct sha1_ctx *ctx, void *digest)
if (ctx->blocklen > 56) {
sha1_compute(ctx, ctx->block);
ctx->blocklen = 0;
memset(ctx->block, 0, 64);
memset(ctx->block, 0, sizeof ctx->block);
}
hi = htobe32(ctx->bitlen >> 32);
lo = htobe32(ctx->bitlen & 0xffffffffUL);

477
lib/digest/sha256.c Normal file
View file

@ -0,0 +1,477 @@
/*-
* Copyright (c) 2005-2013 Colin Percival
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Cryb$
*/
#include "cryb/impl.h"
#ifdef HAVE_SYS_ENDIAN_H
#include <sys/endian.h>
#endif
#ifdef HAVE_ENDIAN_H
#define _BSD_SOURCE
#include <endian.h>
#endif
#include <stdint.h>
#include <string.h>
#include <cryb/digest.h>
#include <cryb/sha256.h>
/*
* Encode a length len/4 vector of (uint32_t) into a length len vector of
* (uint8_t) in big-endian form. Assumes len is a multiple of 4.
*/
static void
be32enc_vect(uint8_t *dst, const uint32_t *src, size_t len)
{
size_t i;
for (i = 0; i < len / 4; i++)
be32enc(dst + i * 4, src[i]);
}
/*
* Decode a big-endian length len vector of (uint8_t) into a length
* len/4 vector of (uint32_t). Assumes len is a multiple of 4.
*/
static void
be32dec_vect(uint32_t *dst, const uint8_t *src, size_t len)
{
size_t i;
for (i = 0; i < len / 4; i++)
dst[i] = be32dec(src + i * 4);
}
/* Elementary functions used by SHA256 */
#define Ch(x, y, z) ((x & (y ^ z)) ^ z)
#define Maj(x, y, z) ((x & (y | z)) | (y & z))
#define SHR(x, n) (x >> n)
#define ROTR(x, n) ((x >> n) | (x << (32 - n)))
#define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
#define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
#define s0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3))
#define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10))
/* SHA256 round function */
#define RND(a, b, c, d, e, f, g, h, k) \
t0 = h + S1(e) + Ch(e, f, g) + k; \
t1 = S0(a) + Maj(a, b, c); \
d += t0; \
h = t0 + t1;
/* Adjusted round function for rotating state */
#define RNDr(S, W, i, k) \
RND(S[(64 - i) % 8], S[(65 - i) % 8], \
S[(66 - i) % 8], S[(67 - i) % 8], \
S[(68 - i) % 8], S[(69 - i) % 8], \
S[(70 - i) % 8], S[(71 - i) % 8], \
W[i] + k)
/*
* SHA256 block compression function. The 256-bit state is transformed via
* the 512-bit input block to produce a new state.
*/
static void
sha256_Transform(uint32_t * state, const uint8_t block[64])
{
uint32_t W[64];
uint32_t S[8];
uint32_t t0, t1;
int i;
/* 1. Prepare message schedule W. */
be32dec_vect(W, block, 64);
for (i = 16; i < 64; i++)
W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16];
/* 2. Initialize working variables. */
memcpy(S, state, 32);
/* 3. Mix. */
RNDr(S, W, 0, 0x428a2f98);
RNDr(S, W, 1, 0x71374491);
RNDr(S, W, 2, 0xb5c0fbcf);
RNDr(S, W, 3, 0xe9b5dba5);
RNDr(S, W, 4, 0x3956c25b);
RNDr(S, W, 5, 0x59f111f1);
RNDr(S, W, 6, 0x923f82a4);
RNDr(S, W, 7, 0xab1c5ed5);
RNDr(S, W, 8, 0xd807aa98);
RNDr(S, W, 9, 0x12835b01);
RNDr(S, W, 10, 0x243185be);
RNDr(S, W, 11, 0x550c7dc3);
RNDr(S, W, 12, 0x72be5d74);
RNDr(S, W, 13, 0x80deb1fe);
RNDr(S, W, 14, 0x9bdc06a7);
RNDr(S, W, 15, 0xc19bf174);
RNDr(S, W, 16, 0xe49b69c1);
RNDr(S, W, 17, 0xefbe4786);
RNDr(S, W, 18, 0x0fc19dc6);
RNDr(S, W, 19, 0x240ca1cc);
RNDr(S, W, 20, 0x2de92c6f);
RNDr(S, W, 21, 0x4a7484aa);
RNDr(S, W, 22, 0x5cb0a9dc);
RNDr(S, W, 23, 0x76f988da);
RNDr(S, W, 24, 0x983e5152);
RNDr(S, W, 25, 0xa831c66d);
RNDr(S, W, 26, 0xb00327c8);
RNDr(S, W, 27, 0xbf597fc7);
RNDr(S, W, 28, 0xc6e00bf3);
RNDr(S, W, 29, 0xd5a79147);
RNDr(S, W, 30, 0x06ca6351);
RNDr(S, W, 31, 0x14292967);
RNDr(S, W, 32, 0x27b70a85);
RNDr(S, W, 33, 0x2e1b2138);
RNDr(S, W, 34, 0x4d2c6dfc);
RNDr(S, W, 35, 0x53380d13);
RNDr(S, W, 36, 0x650a7354);
RNDr(S, W, 37, 0x766a0abb);
RNDr(S, W, 38, 0x81c2c92e);
RNDr(S, W, 39, 0x92722c85);
RNDr(S, W, 40, 0xa2bfe8a1);
RNDr(S, W, 41, 0xa81a664b);
RNDr(S, W, 42, 0xc24b8b70);
RNDr(S, W, 43, 0xc76c51a3);
RNDr(S, W, 44, 0xd192e819);
RNDr(S, W, 45, 0xd6990624);
RNDr(S, W, 46, 0xf40e3585);
RNDr(S, W, 47, 0x106aa070);
RNDr(S, W, 48, 0x19a4c116);
RNDr(S, W, 49, 0x1e376c08);
RNDr(S, W, 50, 0x2748774c);
RNDr(S, W, 51, 0x34b0bcb5);
RNDr(S, W, 52, 0x391c0cb3);
RNDr(S, W, 53, 0x4ed8aa4a);
RNDr(S, W, 54, 0x5b9cca4f);
RNDr(S, W, 55, 0x682e6ff3);
RNDr(S, W, 56, 0x748f82ee);
RNDr(S, W, 57, 0x78a5636f);
RNDr(S, W, 58, 0x84c87814);
RNDr(S, W, 59, 0x8cc70208);
RNDr(S, W, 60, 0x90befffa);
RNDr(S, W, 61, 0xa4506ceb);
RNDr(S, W, 62, 0xbef9a3f7);
RNDr(S, W, 63, 0xc67178f2);
/* 4. Mix local working variables into global state. */
for (i = 0; i < 8; i++)
state[i] += S[i];
/* Clean the stack. */
memset(W, 0, 256);
memset(S, 0, 32);
t0 = t1 = 0;
}
static uint8_t PAD[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* Add padding and terminating bit-count. */
static void
sha256_pad(sha256_ctx * ctx)
{
uint8_t len[8];
uint32_t r, plen;
/*
* Convert length to a vector of bytes -- we do this now rather
* than later because the length will change after we pad.
*/
be64enc(len, ctx->count);
/* Add 1--64 bytes so that the resulting length is 56 mod 64. */
r = (ctx->count >> 3) & 0x3f;
plen = (r < 56) ? (56 - r) : (120 - r);
sha256_update(ctx, PAD, (size_t)plen);
/* Add the terminating bit-count. */
sha256_update(ctx, len, 8);
}
/**
* sha256_init(ctx):
* Initialize the SHA256 context ${ctx}.
*/
void
sha256_init(sha256_ctx * ctx)
{
/* Zero bits processed so far. */
ctx->count = 0;
/* Magic initialization constants. */
ctx->state[0] = 0x6A09E667;
ctx->state[1] = 0xBB67AE85;
ctx->state[2] = 0x3C6EF372;
ctx->state[3] = 0xA54FF53A;
ctx->state[4] = 0x510E527F;
ctx->state[5] = 0x9B05688C;
ctx->state[6] = 0x1F83D9AB;
ctx->state[7] = 0x5BE0CD19;
}
/**
* sha256_update(ctx, in, len):
* Input ${len} bytes from ${in} into the SHA256 context ${ctx}.
*/
void
sha256_update(sha256_ctx * ctx, const void *in, size_t len)
{
uint32_t r;
const uint8_t *src = in;
/* Return immediately if we have nothing to do. */
if (len == 0)
return;
/* Number of bytes left in the buffer from previous updates. */
r = (ctx->count >> 3) & 0x3f;
/* Update number of bits. */
ctx->count += (uint64_t)(len) << 3;
/* Handle the case where we don't need to perform any transforms. */
if (len < 64 - r) {
memcpy(&ctx->buf[r], src, len);
return;
}
/* Finish the current block. */
memcpy(&ctx->buf[r], src, 64 - r);
sha256_Transform(ctx->state, ctx->buf);
src += 64 - r;
len -= 64 - r;
/* Perform complete blocks. */
while (len >= 64) {
sha256_Transform(ctx->state, src);
src += 64;
len -= 64;
}
/* Copy left over data into buffer. */
memcpy(ctx->buf, src, len);
}
/**
* sha256_final(ctx, digest):
* Output the SHA256 hash of the data input to the context ${ctx} into the
* buffer ${digest}.
*/
void
sha256_final(sha256_ctx * ctx, uint8_t digest[SHA256_DIGEST_LEN])
{
/* Add padding. */
sha256_pad(ctx);
/* Write the hash. */
be32enc_vect(digest, ctx->state, SHA256_DIGEST_LEN);
/* Clear the context state. */
memset((void *)ctx, 0, sizeof(*ctx));
}
/**
* sha256_complete(in, len, digest):
* Compute the SHA256 hash of ${len} bytes from $in} and write it to ${digest}.
*/
void
sha256_complete(const void * in, size_t len, uint8_t digest[SHA256_DIGEST_LEN])
{
sha256_ctx ctx;
sha256_init(&ctx);
sha256_update(&ctx, in, len);
sha256_final(&ctx, digest);
}
/**
* hmac_sha256_init(ctx, K, Klen):
* Initialize the HMAC-SHA256 context ${ctx} with ${Klen} bytes of key from
* ${K}.
*/
void
hmac_sha256_init(hmac_sha256_ctx * ctx, const void * _K, size_t Klen)
{
uint8_t pad[64];
uint8_t khash[SHA256_DIGEST_LEN];
const uint8_t * K = _K;
size_t i;
/* If Klen > 64, the key is really SHA256(K). */
if (Klen > 64) {
sha256_init(&ctx->ictx);
sha256_update(&ctx->ictx, K, Klen);
sha256_final(&ctx->ictx, khash);
K = khash;
Klen = sizeof khash;
}
/* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */
sha256_init(&ctx->ictx);
memset(pad, 0x36, 64);
for (i = 0; i < Klen; i++)
pad[i] ^= K[i];
sha256_update(&ctx->ictx, pad, 64);
/* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */
sha256_init(&ctx->octx);
memset(pad, 0x5c, 64);
for (i = 0; i < Klen; i++)
pad[i] ^= K[i];
sha256_update(&ctx->octx, pad, 64);
/* Clean the stack. */
memset(khash, 0, sizeof khash);
memset(pad, 0, 64);
}
/**
* hmac_sha256_update(ctx, in, len):
* Input ${len} bytes from ${in} into the HMAC-SHA256 context ${ctx}.
*/
void
hmac_sha256_update(hmac_sha256_ctx * ctx, const void *in, size_t len)
{
/* Feed data to the inner SHA256 operation. */
sha256_update(&ctx->ictx, in, len);
}
/**
* hmac_sha256_final(ctx, digest):
* Output the HMAC-SHA256 of the data input to the context ${ctx} into the
* buffer ${digest}.
*/
void
hmac_sha256_final(hmac_sha256_ctx * ctx, uint8_t digest[SHA256_DIGEST_LEN])
{
uint8_t ihash[SHA256_DIGEST_LEN];
/* Finish the inner SHA256 operation. */
sha256_final(&ctx->ictx, ihash);
/* Feed the inner hash to the outer SHA256 operation. */
sha256_update(&ctx->octx, ihash, sizeof ihash);
/* Finish the outer SHA256 operation. */
sha256_final(&ctx->octx, digest);
/* Clean the stack. */
memset(ihash, 0, sizeof ihash);
}
/**
* hmac_sha256_complete(K, Klen, in, len, digest):
* Compute the HMAC-SHA256 of ${len} bytes from ${in} using the key ${K} of
* length ${Klen}, and write the result to ${digest}.
*/
void
hmac_sha256_complete(const void * K, size_t Klen, const void * in, size_t len,
uint8_t digest[SHA256_DIGEST_LEN])
{
hmac_sha256_ctx ctx;
hmac_sha256_init(&ctx, K, Klen);
hmac_sha256_update(&ctx, in, len);
hmac_sha256_final(&ctx, digest);
}
/**
* PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
* Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
* write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
*/
void
pbkdf2_sha256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt,
size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen)
{
hmac_sha256_ctx PShctx, hctx;
size_t i;
uint8_t ivec[4];
uint8_t U[SHA256_DIGEST_LEN];
uint8_t T[SHA256_DIGEST_LEN];
uint64_t j;
unsigned int k;
size_t clen;
/* Compute HMAC state after processing P and S. */
hmac_sha256_init(&PShctx, passwd, passwdlen);
hmac_sha256_update(&PShctx, salt, saltlen);
/* Iterate through the blocks. */
for (i = 0; i * 32 < dkLen; i++) {
/* Generate INT(i + 1). */
be32enc(ivec, (uint32_t)(i + 1));
/* Compute U_1 = PRF(P, S || INT(i)). */
memcpy(&hctx, &PShctx, sizeof(hmac_sha256_ctx));
hmac_sha256_update(&hctx, ivec, 4);
hmac_sha256_final(&hctx, U);
/* T_i = U_1 ... */
memcpy(T, U, sizeof T);
for (j = 2; j <= c; j++) {
/* Compute U_j. */
hmac_sha256_init(&hctx, passwd, passwdlen);
hmac_sha256_update(&hctx, U, 32);
hmac_sha256_final(&hctx, U);
/* ... xor U_j ... */
for (k = 0; k < sizeof T; k++)
T[k] ^= U[k];
}
/* Copy as many bytes as necessary into buf. */
clen = dkLen - i * 32;
if (clen > 32)
clen = 32;
memcpy(&buf[i * 32], T, clen);
}
/* Clean PShctx, since we never called _final on it. */
memset(&PShctx, 0, sizeof(hmac_sha256_ctx));
}
struct digest_algorithm sha256_digest = {
.name = "sha256",
.contextlen = sizeof sha256_digest,
.digestlen = SHA256_DIGEST_LEN,
.init = (digest_init_func)sha256_init,
.update = (digest_update_func)sha256_update,
.final = (digest_final_func)sha256_final,
.complete = (digest_complete_func)sha256_complete,
};

419
lib/digest/sha384.c Normal file
View file

@ -0,0 +1,419 @@
/*
* Copyright (c) 2006-2007 Christophe Devine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Cryb$
*/
/*
* The SHA-384 Secure Hash Standard was published by NIST in 2002.
*
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
*/
#include "cryb/impl.h"
#include <stdint.h>
#include <string.h>
#include <cryb/digest.h>
#include <cryb/sha384.h>
static int is384 = 1;
/*
* 64-bit integer manipulation macros (big endian)
*/
#ifndef GET_UINT64_BE
#define GET_UINT64_BE(n,b,i) \
do { \
(n) = ( (uint64_t) (b)[(i) ] << 56 ) \
| ( (uint64_t) (b)[(i) + 1] << 48 ) \
| ( (uint64_t) (b)[(i) + 2] << 40 ) \
| ( (uint64_t) (b)[(i) + 3] << 32 ) \
| ( (uint64_t) (b)[(i) + 4] << 24 ) \
| ( (uint64_t) (b)[(i) + 5] << 16 ) \
| ( (uint64_t) (b)[(i) + 6] << 8 ) \
| ( (uint64_t) (b)[(i) + 7] ); \
} while (0)
#endif
#ifndef PUT_UINT64_BE
#define PUT_UINT64_BE(n,b,i) \
do { \
(b)[(i) ] = (unsigned char) ( (n) >> 56 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \
(b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \
(b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 7] = (unsigned char) ( (n) ); \
} while (0)
#endif
/* XXX */
#define UL64(x) x##ULL
/*
* Round constants
*/
static const uint64_t K[80] =
{
UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD),
UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC),
UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019),
UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118),
UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE),
UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2),
UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1),
UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694),
UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3),
UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65),
UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483),
UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5),
UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210),
UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4),
UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725),
UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70),
UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926),
UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF),
UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8),
UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B),
UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001),
UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30),
UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910),
UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8),
UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53),
UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8),
UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB),
UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3),
UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60),
UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC),
UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9),
UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B),
UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207),
UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178),
UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6),
UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B),
UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493),
UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C),
UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A),
UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817)
};
/*
* SHA-384 context setup
*/
void sha384_init( sha384_ctx *ctx )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
if( is384 == 0 )
{
/* SHA-384 */
ctx->state[0] = UL64(0x6A09E667F3BCC908);
ctx->state[1] = UL64(0xBB67AE8584CAA73B);
ctx->state[2] = UL64(0x3C6EF372FE94F82B);
ctx->state[3] = UL64(0xA54FF53A5F1D36F1);
ctx->state[4] = UL64(0x510E527FADE682D1);
ctx->state[5] = UL64(0x9B05688C2B3E6C1F);
ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);
ctx->state[7] = UL64(0x5BE0CD19137E2179);
}
else
{
/* SHA-384 */
ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
ctx->state[1] = UL64(0x629A292A367CD507);
ctx->state[2] = UL64(0x9159015A3070DD17);
ctx->state[3] = UL64(0x152FECD8F70E5939);
ctx->state[4] = UL64(0x67332667FFC00B31);
ctx->state[5] = UL64(0x8EB44A8768581511);
ctx->state[6] = UL64(0xDB0C2E0D64F98FA7);
ctx->state[7] = UL64(0x47B5481DBEFA4FA4);
}
}
static void sha384_process( sha384_ctx *ctx, const unsigned char *data )
{
int i;
uint64_t temp1, temp2, W[80];
uint64_t A, B, C, D, E, F, G, H;
#define SHR(x,n) (x >> n)
#define ROTR(x,n) (SHR(x,n) | (x << (64 - n)))
#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6))
#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
#define F0(x,y,z) ((x & y) | (z & (x | y)))
#define F1(x,y,z) (z ^ (x & (y ^ z)))
#define P(a,b,c,d,e,f,g,h,x,K) \
{ \
temp1 = h + S3(e) + F1(e,f,g) + K + x; \
temp2 = S2(a) + F0(a,b,c); \
d += temp1; h = temp1 + temp2; \
}
for( i = 0; i < 16; i++ )
{
GET_UINT64_BE( W[i], data, i << 3 );
}
for( ; i < 80; i++ )
{
W[i] = S1(W[i - 2]) + W[i - 7] +
S0(W[i - 15]) + W[i - 16];
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
F = ctx->state[5];
G = ctx->state[6];
H = ctx->state[7];
i = 0;
do
{
P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++;
P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++;
P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++;
P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++;
P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++;
P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++;
P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++;
P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++;
}
while( i < 80 );
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
ctx->state[5] += F;
ctx->state[6] += G;
ctx->state[7] += H;
}
/*
* SHA-384 process buffer
*/
void sha384_update( sha384_ctx *ctx, const void *input, int ilen )
{
int fill;
uint64_t left;
if( ilen <= 0 )
return;
left = ctx->total[0] & 0x7F;
fill = (int)( 128 - left );
ctx->total[0] += ilen;
if( ctx->total[0] < (uint64_t) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, fill );
sha384_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 128 )
{
sha384_process( ctx, input );
input += 128;
ilen -= 128;
}
if( ilen > 0 )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, ilen );
}
}
static const unsigned char sha384_padding[128] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SHA-384 final digest
*/
void sha384_final( sha384_ctx *ctx, unsigned char output[64] )
{
int last, padn;
uint64_t high, low;
unsigned char msglen[16];
high = ( ctx->total[0] >> 61 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT64_BE( high, msglen, 0 );
PUT_UINT64_BE( low, msglen, 8 );
last = (int)( ctx->total[0] & 0x7F );
padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last );
sha384_update( ctx, (unsigned char *) sha384_padding, padn );
sha384_update( ctx, msglen, 16 );
PUT_UINT64_BE( ctx->state[0], output, 0 );
PUT_UINT64_BE( ctx->state[1], output, 8 );
PUT_UINT64_BE( ctx->state[2], output, 16 );
PUT_UINT64_BE( ctx->state[3], output, 24 );
PUT_UINT64_BE( ctx->state[4], output, 32 );
PUT_UINT64_BE( ctx->state[5], output, 40 );
if( is384 == 0 )
{
PUT_UINT64_BE( ctx->state[6], output, 48 );
PUT_UINT64_BE( ctx->state[7], output, 56 );
}
}
/*
* output = SHA-384( input buffer )
*/
void sha384_complete( const void *input, int ilen,
unsigned char output[64] )
{
sha384_ctx ctx;
sha384_init( &ctx );
sha384_update( &ctx, input, ilen );
sha384_final( &ctx, output );
memset( &ctx, 0, sizeof( sha384_ctx ) );
}
/*
* SHA-384 HMAC context setup
*/
void sha384_hmac_init( sha384_ctx *ctx, unsigned char *key, int keylen )
{
int i;
unsigned char sum[64];
if( keylen > 128 )
{
sha384_complete( key, keylen, sum );
keylen = ( is384 ) ? 48 : 64;
key = sum;
}
memset( ctx->ipad, 0x36, 128 );
memset( ctx->opad, 0x5C, 128 );
for( i = 0; i < keylen; i++ )
{
ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
}
sha384_init( ctx );
sha384_update( ctx, ctx->ipad, 128 );
memset( sum, 0, sizeof( sum ) );
}
/*
* SHA-384 HMAC process buffer
*/
void sha384_hmac_update( sha384_ctx *ctx,
unsigned char *input, int ilen )
{
sha384_update( ctx, input, ilen );
}
/*
* SHA-384 HMAC final digest
*/
void sha384_hmac_final( sha384_ctx *ctx, unsigned char output[64] )
{
int hlen;
unsigned char tmpbuf[64];
hlen = ( is384 == 0 ) ? 64 : 48;
sha384_final( ctx, tmpbuf );
sha384_init( ctx );
sha384_update( ctx, ctx->opad, 128 );
sha384_update( ctx, tmpbuf, hlen );
sha384_final( ctx, output );
memset( tmpbuf, 0, sizeof( tmpbuf ) );
}
/*
* output = HMAC-SHA-384( hmac key, input buffer )
*/
void sha384_hmac_complete( unsigned char *key, int keylen,
unsigned char *input, int ilen,
unsigned char output[64] )
{
sha384_ctx ctx;
sha384_hmac_init( &ctx, key, keylen );
sha384_hmac_update( &ctx, input, ilen );
sha384_hmac_final( &ctx, output );
memset( &ctx, 0, sizeof( sha384_ctx ) );
}
struct digest_algorithm sha384_digest = {
.name = "sha384",
.contextlen = sizeof sha384_digest,
.digestlen = SHA384_DIGEST_LEN,
.init = (digest_init_func)sha384_init,
.update = (digest_update_func)sha384_update,
.final = (digest_final_func)sha384_final,
.complete = (digest_complete_func)sha384_complete,
};

419
lib/digest/sha512.c Normal file
View file

@ -0,0 +1,419 @@
/*
* Copyright (c) 2006-2007 Christophe Devine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Cryb$
*/
/*
* The SHA-512 Secure Hash Standard was published by NIST in 2002.
*
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
*/
#include "cryb/impl.h"
#include <stdint.h>
#include <string.h>
#include <cryb/digest.h>
#include <cryb/sha512.h>
static int is384 = 0;
/*
* 64-bit integer manipulation macros (big endian)
*/
#ifndef GET_UINT64_BE
#define GET_UINT64_BE(n,b,i) \
do { \
(n) = ( (uint64_t) (b)[(i) ] << 56 ) \
| ( (uint64_t) (b)[(i) + 1] << 48 ) \
| ( (uint64_t) (b)[(i) + 2] << 40 ) \
| ( (uint64_t) (b)[(i) + 3] << 32 ) \
| ( (uint64_t) (b)[(i) + 4] << 24 ) \
| ( (uint64_t) (b)[(i) + 5] << 16 ) \
| ( (uint64_t) (b)[(i) + 6] << 8 ) \
| ( (uint64_t) (b)[(i) + 7] ); \
} while (0)
#endif
#ifndef PUT_UINT64_BE
#define PUT_UINT64_BE(n,b,i) \
do { \
(b)[(i) ] = (unsigned char) ( (n) >> 56 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \
(b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \
(b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 7] = (unsigned char) ( (n) ); \
} while (0)
#endif
/* XXX */
#define UL64(x) x##ULL
/*
* Round constants
*/
static const uint64_t K[80] =
{
UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD),
UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC),
UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019),
UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118),
UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE),
UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2),
UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1),
UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694),
UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3),
UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65),
UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483),
UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5),
UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210),
UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4),
UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725),
UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70),
UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926),
UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF),
UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8),
UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B),
UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001),
UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30),
UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910),
UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8),
UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53),
UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8),
UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB),
UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3),
UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60),
UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC),
UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9),
UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B),
UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207),
UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178),
UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6),
UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B),
UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493),
UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C),
UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A),
UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817)
};
/*
* SHA-512 context setup
*/
void sha512_init( sha512_ctx *ctx )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
if( is384 == 0 )
{
/* SHA-512 */
ctx->state[0] = UL64(0x6A09E667F3BCC908);
ctx->state[1] = UL64(0xBB67AE8584CAA73B);
ctx->state[2] = UL64(0x3C6EF372FE94F82B);
ctx->state[3] = UL64(0xA54FF53A5F1D36F1);
ctx->state[4] = UL64(0x510E527FADE682D1);
ctx->state[5] = UL64(0x9B05688C2B3E6C1F);
ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);
ctx->state[7] = UL64(0x5BE0CD19137E2179);
}
else
{
/* SHA-384 */
ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
ctx->state[1] = UL64(0x629A292A367CD507);
ctx->state[2] = UL64(0x9159015A3070DD17);
ctx->state[3] = UL64(0x152FECD8F70E5939);
ctx->state[4] = UL64(0x67332667FFC00B31);
ctx->state[5] = UL64(0x8EB44A8768581511);
ctx->state[6] = UL64(0xDB0C2E0D64F98FA7);
ctx->state[7] = UL64(0x47B5481DBEFA4FA4);
}
}
static void sha512_process( sha512_ctx *ctx, const unsigned char *data )
{
int i;
uint64_t temp1, temp2, W[80];
uint64_t A, B, C, D, E, F, G, H;
#define SHR(x,n) (x >> n)
#define ROTR(x,n) (SHR(x,n) | (x << (64 - n)))
#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6))
#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
#define F0(x,y,z) ((x & y) | (z & (x | y)))
#define F1(x,y,z) (z ^ (x & (y ^ z)))
#define P(a,b,c,d,e,f,g,h,x,K) \
{ \
temp1 = h + S3(e) + F1(e,f,g) + K + x; \
temp2 = S2(a) + F0(a,b,c); \
d += temp1; h = temp1 + temp2; \
}
for( i = 0; i < 16; i++ )
{
GET_UINT64_BE( W[i], data, i << 3 );
}
for( ; i < 80; i++ )
{
W[i] = S1(W[i - 2]) + W[i - 7] +
S0(W[i - 15]) + W[i - 16];
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
F = ctx->state[5];
G = ctx->state[6];
H = ctx->state[7];
i = 0;
do
{
P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++;
P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++;
P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++;
P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++;
P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++;
P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++;
P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++;
P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++;
}
while( i < 80 );
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
ctx->state[5] += F;
ctx->state[6] += G;
ctx->state[7] += H;
}
/*
* SHA-512 process buffer
*/
void sha512_update( sha512_ctx *ctx, const void *input, int ilen )
{
int fill;
uint64_t left;
if( ilen <= 0 )
return;
left = ctx->total[0] & 0x7F;
fill = (int)( 128 - left );
ctx->total[0] += ilen;
if( ctx->total[0] < (uint64_t) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, fill );
sha512_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 128 )
{
sha512_process( ctx, input );
input += 128;
ilen -= 128;
}
if( ilen > 0 )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, ilen );
}
}
static const unsigned char sha512_padding[128] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SHA-512 final digest
*/
void sha512_final( sha512_ctx *ctx, unsigned char output[64] )
{
int last, padn;
uint64_t high, low;
unsigned char msglen[16];
high = ( ctx->total[0] >> 61 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT64_BE( high, msglen, 0 );
PUT_UINT64_BE( low, msglen, 8 );
last = (int)( ctx->total[0] & 0x7F );
padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last );
sha512_update( ctx, (unsigned char *) sha512_padding, padn );
sha512_update( ctx, msglen, 16 );
PUT_UINT64_BE( ctx->state[0], output, 0 );
PUT_UINT64_BE( ctx->state[1], output, 8 );
PUT_UINT64_BE( ctx->state[2], output, 16 );
PUT_UINT64_BE( ctx->state[3], output, 24 );
PUT_UINT64_BE( ctx->state[4], output, 32 );
PUT_UINT64_BE( ctx->state[5], output, 40 );
if( is384 == 0 )
{
PUT_UINT64_BE( ctx->state[6], output, 48 );
PUT_UINT64_BE( ctx->state[7], output, 56 );
}
}
/*
* output = SHA-512( input buffer )
*/
void sha512_complete( const void *input, int ilen,
unsigned char output[64] )
{
sha512_ctx ctx;
sha512_init( &ctx );
sha512_update( &ctx, input, ilen );
sha512_final( &ctx, output );
memset( &ctx, 0, sizeof( sha512_ctx ) );
}
/*
* SHA-512 HMAC context setup
*/
void sha512_hmac_init( sha512_ctx *ctx, unsigned char *key, int keylen )
{
int i;
unsigned char sum[64];
if( keylen > 128 )
{
sha512_complete( key, keylen, sum );
keylen = ( is384 ) ? 48 : 64;
key = sum;
}
memset( ctx->ipad, 0x36, 128 );
memset( ctx->opad, 0x5C, 128 );
for( i = 0; i < keylen; i++ )
{
ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
}
sha512_init( ctx );
sha512_update( ctx, ctx->ipad, 128 );
memset( sum, 0, sizeof( sum ) );
}
/*
* SHA-512 HMAC process buffer
*/
void sha512_hmac_update( sha512_ctx *ctx,
unsigned char *input, int ilen )
{
sha512_update( ctx, input, ilen );
}
/*
* SHA-512 HMAC final digest
*/
void sha512_hmac_final( sha512_ctx *ctx, unsigned char output[64] )
{
int hlen;
unsigned char tmpbuf[64];
hlen = ( is384 == 0 ) ? 64 : 48;
sha512_final( ctx, tmpbuf );
sha512_init( ctx );
sha512_update( ctx, ctx->opad, 128 );
sha512_update( ctx, tmpbuf, hlen );
sha512_final( ctx, output );
memset( tmpbuf, 0, sizeof( tmpbuf ) );
}
/*
* output = HMAC-SHA-512( hmac key, input buffer )
*/
void sha512_hmac_complete( unsigned char *key, int keylen,
unsigned char *input, int ilen,
unsigned char output[64] )
{
sha512_ctx ctx;
sha512_hmac_init( &ctx, key, keylen );
sha512_hmac_update( &ctx, input, ilen );
sha512_hmac_final( &ctx, output );
memset( &ctx, 0, sizeof( sha512_ctx ) );
}
struct digest_algorithm sha512_digest = {
.name = "sha512",
.contextlen = sizeof sha512_digest,
.digestlen = SHA512_DIGEST_LEN,
.init = (digest_init_func)sha512_init,
.update = (digest_update_func)sha512_update,
.final = (digest_final_func)sha512_final,
.complete = (digest_complete_func)sha512_complete,
};

View file

@ -45,26 +45,41 @@ TESTS += t_ctype
TESTS += t_rfc3986 t_rfc4648
# libcryb-digest
TESTS += t_md5
TESTS += t_md2 t_md4 t_md5
if WITH_OPENSSL
TESTS += t_md5_openssl
TESTS += t_md4_openssl t_md5_openssl
t_md4_openssl_SOURCES = t_md4.c
t_md4_openssl_CFLAGS = $(OPENSSL_INCLUDES) $(OPENSSL_CFLAGS)
t_md4_openssl_LDADD = $(OPENSSL_LDADD)
t_md5_openssl_SOURCES = t_md5.c
t_md5_openssl_CFLAGS = $(OPENSSL_INCLUDES) $(OPENSSL_CFLAGS)
t_md5_openssl_LDADD = $(OPENSSL_LDADD)
endif
if WITH_RSAREF
TESTS += t_md5_rsaref
TESTS += t_md2_rsaref t_md5_rsaref
t_md2_rsaref_SOURCES = t_md2.c
t_md2_rsaref_CFLAGS = $(RSAREF_INCLUDES) $(RSAREF_CFLAGS)
t_md2_rsaref_LDADD = $(RSAREF_LDADD)
t_md5_rsaref_SOURCES = t_md5.c
t_md5_rsaref_CFLAGS = $(RSAREF_INCLUDES) $(RSAREF_CFLAGS)
t_md5_rsaref_LDADD = $(RSAREF_LDADD)
endif
TESTS += t_sha1
TESTS += t_sha1 t_sha256 t_sha384 t_sha512
if WITH_OPENSSL
TESTS += t_sha1_openssl
TESTS += t_sha1_openssl t_sha256_openssl t_sha384_openssl t_sha512_openssl
t_sha1_openssl_SOURCES = t_sha1.c
t_sha1_openssl_CFLAGS = $(OPENSSL_INCLUDES) $(OPENSSL_CFLAGS)
t_sha1_openssl_LDADD = $(OPENSSL_LDADD)
t_sha256_openssl_SOURCES = t_sha256.c
t_sha256_openssl_CFLAGS = $(OPENSSL_INCLUDES) $(OPENSSL_CFLAGS)
t_sha256_openssl_LDADD = $(OPENSSL_LDADD)
t_sha384_openssl_SOURCES = t_sha384.c
t_sha384_openssl_CFLAGS = $(OPENSSL_INCLUDES) $(OPENSSL_CFLAGS)
t_sha384_openssl_LDADD = $(OPENSSL_LDADD)
t_sha512_openssl_SOURCES = t_sha512.c
t_sha512_openssl_CFLAGS = $(OPENSSL_INCLUDES) $(OPENSSL_CFLAGS)
t_sha512_openssl_LDADD = $(OPENSSL_LDADD)
endif
# libcryb-mac

257
t/t_md2.c Normal file
View file

@ -0,0 +1,257 @@
/*-
* Copyright (c) 2012 Universitetet i Oslo
* Copyright (c) 2012-2014 Dag-Erling Smørgrav
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Cryb$
*/
#include "cryb/impl.h"
#include <err.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "t.h"
#if WITH_RSAREF
#include <rsaref.h>
#define MD2_DIGEST_LEN 16
static void
t_md2_complete(const void *msg, size_t msglen, uint8_t *digest)
{
MD2_CTX ctx;
MD2Init(&ctx);
MD2Update(&ctx, (unsigned char *)(uintptr_t)msg, msglen);
MD2Final(digest, &ctx);
}
#else
#include <cryb/md2.h>
#define t_md2_complete(msg, msglen, digest) \
md2_complete(msg, msglen, digest)
#endif
/*
* Test vectors from RFC 1319
*/
static struct t_vector {
const char *msg;
const uint8_t digest[MD2_DIGEST_LEN];
} t_md2_vectors[] = {
{
"",
{
0x83, 0x50, 0xe5, 0xa3, 0xe2, 0x4c, 0x15, 0x3d,
0xf2, 0x27, 0x5c, 0x9f, 0x80, 0x69, 0x27, 0x73,
}
},
{
"a",
{
0x32, 0xec, 0x01, 0xec, 0x4a, 0x6d, 0xac, 0x72,
0xc0, 0xab, 0x96, 0xfb, 0x34, 0xc0, 0xb5, 0xd1,
}
},
{
"abc",
{
0xda, 0x85, 0x3b, 0x0d, 0x3f, 0x88, 0xd9, 0x9b,
0x30, 0x28, 0x3a, 0x69, 0xe6, 0xde, 0xd6, 0xbb,
}
},
{
"message digest",
{
0xab, 0x4f, 0x49, 0x6b, 0xfb, 0x2a, 0x53, 0x0b,
0x21, 0x9f, 0xf3, 0x30, 0x31, 0xfe, 0x06, 0xb0,
}
},
{
"abcdefghijklmnopqrstuvwxyz",
{
0x4e, 0x8d, 0xdf, 0xf3, 0x65, 0x02, 0x92, 0xab,
0x5a, 0x41, 0x08, 0xc3, 0xaa, 0x47, 0x94, 0x0b,
}
},
{
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789",
{
0xda, 0x33, 0xde, 0xf2, 0xa4, 0x2d, 0xf1, 0x39,
0x75, 0x35, 0x28, 0x46, 0xc3, 0x03, 0x38, 0xcd,
}
},
{
"1234567890123456789012345678901234567890"
"1234567890123456789012345678901234567890",
{
0xd5, 0x97, 0x6f, 0x79, 0xd8, 0x3d, 0x3a, 0x0d,
0xc9, 0x80, 0x6c, 0x3c, 0x66, 0xf3, 0xef, 0xd8,
}
},
};
/*
* Unit test: compute the MD2 sum of the specified string and compare it
* to the expected result.
*/
static int
t_md2_vector(char **desc CRYB_UNUSED, void *arg)
{
struct t_vector *vector = (struct t_vector *)arg;
uint8_t digest[MD2_DIGEST_LEN];
t_md2_complete(vector->msg, strlen(vector->msg), digest);
if (memcmp(digest, vector->digest, MD2_DIGEST_LEN) != 0) {
t_verbose("expected ");
t_verbose_hex(vector->digest, MD2_DIGEST_LEN);
t_verbose("\n");
t_verbose("got ");
t_verbose_hex(digest, MD2_DIGEST_LEN);
t_verbose("\n");
return (0);
}
return (1);
}
#ifdef BENCHMARKS
/*
* Performance test: measure the time spent computing the MD2 sum of a
* message of the specified length.
*/
#define T_PERF_ITERATIONS 1000
static int
t_md2_perf(char **desc, void *arg)
{
struct timespec ts, te;
unsigned long ns;
uint8_t digest[MD2_DIGEST_LEN];
char *msg, *comment;
size_t msglen = *(size_t *)arg;
if ((msg = calloc(1, msglen)) == NULL)
err(1, "calloc()");
clock_gettime(CLOCK_MONOTONIC_PRECISE, &ts);
for (int i = 0; i < T_PERF_ITERATIONS; ++i)
t_md2_complete(msg, msglen, digest);
clock_gettime(CLOCK_MONOTONIC_PRECISE, &te);
free(msg);
ns = te.tv_sec * 1000000000LU + te.tv_nsec;
ns -= ts.tv_sec * 1000000000LU + ts.tv_nsec;
asprintf(&comment, "%zu bytes: %d iterations in %'lu ns",
msglen, T_PERF_ITERATIONS, ns);
if (comment == NULL)
err(1, "asprintf()");
*desc = comment;
return (1);
}
#endif
#if !defined(WITH_RSAREF)
/*
* Various corner cases and error conditions
*/
static int
t_md2_short_updates(char **desc CRYB_UNUSED, void *arg)
{
struct t_vector *vector = (struct t_vector *)arg;
uint8_t digest[MD2_DIGEST_LEN];
md2_ctx ctx;
int i, len;
md2_init(&ctx);
len = strlen(vector->msg);
for (i = 0; i + 5 < len; i += 5)
md2_update(&ctx, vector->msg + i, 5);
md2_update(&ctx, vector->msg + i, len - i);
md2_final(&ctx, digest);
return (memcmp(digest, vector->digest, MD2_DIGEST_LEN) == 0);
}
#endif
/***************************************************************************
* Boilerplate
*/
int
t_prepare(int argc, char *argv[])
{
int i, n;
(void)argc;
(void)argv;
n = sizeof t_md2_vectors / sizeof t_md2_vectors[0];
for (i = 0; i < n; ++i)
t_add_test(t_md2_vector, &t_md2_vectors[i],
"RFC 1321 test vector %d", i + 1);
#if !defined(WITH_RSAREF)
/*
* Run test vector 7 (which is 80 characters long) 5 characters at
* a time. This tests a) appending data to an underfull block and
* b) appending more data to an underfull block than it has room
* for (since 64 % 5 != 0). Test vector 7 already exercised the
* code path for computing a block directly from source (without
* copying it in), and all the test vectors except vector 1
* exercised the general case of copying a small amount of data in
* without crossing the block boundary.
*/
t_add_test(t_md2_short_updates, &t_md2_vectors[6],
"multiple short updates");
#endif
#ifdef BENCHMARKS
static size_t one = 1, thousand = 1000, million = 1000000;
t_add_test(t_md2_perf, &one,
"performance test (1 byte)");
t_add_test(t_md2_perf, &thousand,
"performance test (1,000 bytes)");
t_add_test(t_md2_perf, &million,
"performance test (1,000,000 bytes)");
#endif
return (0);
}
void
t_cleanup(void)
{
}

273
t/t_md4.c Normal file
View file

@ -0,0 +1,273 @@
/*-
* Copyright (c) 2012 Universitetet i Oslo
* Copyright (c) 2012-2014 Dag-Erling Smørgrav
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Cryb$
*/
#include "cryb/impl.h"
#include <err.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "t.h"
#if WITH_OPENSSL
#include <openssl/md4.h>
#define MD4_DIGEST_LEN MD4_DIGEST_LENGTH
static void
t_md4_complete(const void *msg, size_t msglen, uint8_t *digest)
{
MD4_CTX ctx;
MD4_Init(&ctx);
MD4_Update(&ctx, msg, msglen);
MD4_Final(digest, &ctx);
}
#elif WITH_RSAREF
#include <rsaref.h>
#define MD4_DIGEST_LEN 16
static void
t_md4_complete(const void *msg, size_t msglen, uint8_t *digest)
{
MD4_CTX ctx;
MD4Init(&ctx);
MD4Update(&ctx, (unsigned char *)(uintptr_t)msg, msglen);
MD4Final(digest, &ctx);
}
#else
#include <cryb/md4.h>
#define t_md4_complete(msg, msglen, digest) \
md4_complete(msg, msglen, digest)
#endif
/*
* Test vectors from RFC 1320
*/
static struct t_vector {
const char *msg;
const uint8_t digest[MD4_DIGEST_LEN];
} t_md4_vectors[] = {
{
"",
{
0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31,
0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0,
}
},
{
"a",
{
0xbd, 0xe5, 0x2c, 0xb3, 0x1d, 0xe3, 0x3e, 0x46,
0x24, 0x5e, 0x05, 0xfb, 0xdb, 0xd6, 0xfb, 0x24,
}
},
{
"abc",
{
0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52,
0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d,
}
},
{
"message digest",
{
0xd9, 0x13, 0x0a, 0x81, 0x64, 0x54, 0x9f, 0xe8,
0x18, 0x87, 0x48, 0x06, 0xe1, 0xc7, 0x01, 0x4b,
}
},
{
"abcdefghijklmnopqrstuvwxyz",
{
0xd7, 0x9e, 0x1c, 0x30, 0x8a, 0xa5, 0xbb, 0xcd,
0xee, 0xa8, 0xed, 0x63, 0xdf, 0x41, 0x2d, 0xa9,
}
},
{
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789",
{
0x04, 0x3f, 0x85, 0x82, 0xf2, 0x41, 0xdb, 0x35,
0x1c, 0xe6, 0x27, 0xe1, 0x53, 0xe7, 0xf0, 0xe4,
}
},
{
"1234567890123456789012345678901234567890"
"1234567890123456789012345678901234567890",
{
0xe3, 0x3b, 0x4d, 0xdc, 0x9c, 0x38, 0xf2, 0x19,
0x9c, 0x3e, 0x7b, 0x16, 0x4f, 0xcc, 0x05, 0x36,
}
},
};
/*
* Unit test: compute the MD4 sum of the specified string and compare it
* to the expected result.
*/
static int
t_md4_vector(char **desc CRYB_UNUSED, void *arg)
{
struct t_vector *vector = (struct t_vector *)arg;
uint8_t digest[MD4_DIGEST_LEN];
t_md4_complete(vector->msg, strlen(vector->msg), digest);
if (memcmp(digest, vector->digest, MD4_DIGEST_LEN) != 0) {
t_verbose("expected ");
t_verbose_hex(vector->digest, MD4_DIGEST_LEN);
t_verbose("\n");
t_verbose("got ");
t_verbose_hex(digest, MD4_DIGEST_LEN);
t_verbose("\n");
return (0);
}
return (1);
}
#ifdef BENCHMARKS
/*
* Performance test: measure the time spent computing the MD4 sum of a
* message of the specified length.
*/
#define T_PERF_ITERATIONS 1000
static int
t_md4_perf(char **desc, void *arg)
{
struct timespec ts, te;
unsigned long ns;
uint8_t digest[MD4_DIGEST_LEN];
char *msg, *comment;
size_t msglen = *(size_t *)arg;
if ((msg = calloc(1, msglen)) == NULL)
err(1, "calloc()");
clock_gettime(CLOCK_MONOTONIC_PRECISE, &ts);
for (int i = 0; i < T_PERF_ITERATIONS; ++i)
t_md4_complete(msg, msglen, digest);
clock_gettime(CLOCK_MONOTONIC_PRECISE, &te);
free(msg);
ns = te.tv_sec * 1000000000LU + te.tv_nsec;
ns -= ts.tv_sec * 1000000000LU + ts.tv_nsec;
asprintf(&comment, "%zu bytes: %d iterations in %'lu ns",
msglen, T_PERF_ITERATIONS, ns);
if (comment == NULL)
err(1, "asprintf()");
*desc = comment;
return (1);
}
#endif
#if !defined(WITH_OPENSSL) && !defined(WITH_RSAREF)
/*
* Various corner cases and error conditions
*/
static int
t_md4_short_updates(char **desc CRYB_UNUSED, void *arg)
{
struct t_vector *vector = (struct t_vector *)arg;
uint8_t digest[MD4_DIGEST_LEN];
md4_ctx ctx;
int i, len;
md4_init(&ctx);
len = strlen(vector->msg);
for (i = 0; i + 5 < len; i += 5)
md4_update(&ctx, vector->msg + i, 5);
md4_update(&ctx, vector->msg + i, len - i);
md4_final(&ctx, digest);
return (memcmp(digest, vector->digest, MD4_DIGEST_LEN) == 0);
}
#endif
/***************************************************************************
* Boilerplate
*/
int
t_prepare(int argc, char *argv[])
{
int i, n;
(void)argc;
(void)argv;
n = sizeof t_md4_vectors / sizeof t_md4_vectors[0];
for (i = 0; i < n; ++i)
t_add_test(t_md4_vector, &t_md4_vectors[i],
"RFC 1321 test vector %d", i + 1);
#if !defined(WITH_OPENSSL) && !defined(WITH_RSAREF)
/*
* Run test vector 7 (which is 80 characters long) 5 characters at
* a time. This tests a) appending data to an underfull block and
* b) appending more data to an underfull block than it has room
* for (since 64 % 5 != 0). Test vector 7 already exercised the
* code path for computing a block directly from source (without
* copying it in), and all the test vectors except vector 1
* exercised the general case of copying a small amount of data in
* without crossing the block boundary.
*/
t_add_test(t_md4_short_updates, &t_md4_vectors[6],
"multiple short updates");
#endif
#ifdef BENCHMARKS
static size_t one = 1, thousand = 1000, million = 1000000;
t_add_test(t_md4_perf, &one,
"performance test (1 byte)");
t_add_test(t_md4_perf, &thousand,
"performance test (1,000 bytes)");
t_add_test(t_md4_perf, &million,
"performance test (1,000,000 bytes)");
#endif
return (0);
}
void
t_cleanup(void)
{
}

275
t/t_sha256.c Normal file
View file

@ -0,0 +1,275 @@
/*-
* Copyright (c) 2012 Universitetet i Oslo
* Copyright (c) 2012-2014 Dag-Erling Smørgrav
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Cryb$
*/
#include "cryb/impl.h"
#include <err.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "t.h"
#if WITH_OPENSSL
#include <openssl/sha.h>
#define SHA256_DIGEST_LEN SHA256_DIGEST_LENGTH
static void
t_sha256_complete(const void *msg, size_t msglen, uint8_t *digest)
{
SHA256_CTX ctx;
SHA256_Init(&ctx);
SHA256_Update(&ctx, msg, msglen);
SHA256_Final(digest, &ctx);
}
#else
#include <cryb/sha256.h>
#define t_sha256_complete(msg, msglen, digest) \
sha256_complete(msg, msglen, digest)
#endif
static struct t_vector {
const char *desc;
const char *msg;
const uint8_t digest[SHA256_DIGEST_LEN];
} t_sha256_vectors[] = {
{
"zero-length message",
"",
{
0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55,
}
},
{
"FIPS 180-2 B.1 (one-block message)",
"abc",
{
0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad,
}
},
{
/*
* This message is *just* long enough to necessitate a
* second block, which consists entirely of padding.
*/
"FIPS 180-2 B.2 (multi-block message)",
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
{
0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1,
}
},
{
/*
* 1,000,000 x 'a', filled in by t_prepare()
*/
"FIPS 180-2 B.3 (long message)",
NULL,
{
0xcd, 0xc7, 0x6e, 0x5c, 0x99, 0x14, 0xfb, 0x92,
0x81, 0xa1, 0xc7, 0xe2, 0x84, 0xd7, 0x3e, 0x67,
0xf1, 0x80, 0x9a, 0x48, 0xa4, 0x97, 0x20, 0x0e,
0x04, 0x6d, 0x39, 0xcc, 0xc7, 0x11, 0x2c, 0xd0,
},
},
{
/*
* One of the MD5 test vectors, included for the "short
* update" test.
*/
"\"1234567890\"x8",
"1234567890123456789012345678901234567890"
"1234567890123456789012345678901234567890",
{
0xf3, 0x71, 0xbc, 0x4a, 0x31, 0x1f, 0x2b, 0x00,
0x9e, 0xef, 0x95, 0x2d, 0xd8, 0x3c, 0xa8, 0x0e,
0x2b, 0x60, 0x02, 0x6c, 0x8e, 0x93, 0x55, 0x92,
0xd0, 0xf9, 0xc3, 0x08, 0x45, 0x3c, 0x81, 0x3e,
},
},
};
/*
* Unit test: compute the SHA256 sum of the specified string and compare it
* to the expected result.
*/
static int
t_sha256_vector(char **desc CRYB_UNUSED, void *arg)
{
struct t_vector *vector = (struct t_vector *)arg;
uint8_t digest[SHA256_DIGEST_LEN];
char *msg;
if (vector->msg) {
t_sha256_complete(vector->msg, strlen(vector->msg), digest);
} else {
/* special case for FIPS test vector 3 */
if ((msg = malloc(1000000)) == NULL)
err(1, "malloc()");
memset(msg, 'a', 1000000);
t_sha256_complete(msg, 1000000, digest);
free(msg);
}
if (memcmp(digest, vector->digest, SHA256_DIGEST_LEN) != 0) {
t_verbose("expected ");
t_verbose_hex(vector->digest, SHA256_DIGEST_LEN);
t_verbose("\n");
t_verbose("got ");
t_verbose_hex(digest, SHA256_DIGEST_LEN);
t_verbose("\n");
return (0);
}
return (1);
}
#if !defined(WITH_OPENSSL) && !defined(WITH_RSAREF)
/*
* Various corner cases and error conditions
*/
static int
t_sha256_short_updates(char **desc CRYB_UNUSED, void *arg)
{
struct t_vector *vector = (struct t_vector *)arg;
uint8_t digest[SHA256_DIGEST_LEN];
sha256_ctx ctx;
int i, len;
sha256_init(&ctx);
len = strlen(vector->msg);
for (i = 0; i + 5 < len; i += 5)
sha256_update(&ctx, vector->msg + i, 5);
sha256_update(&ctx, vector->msg + i, len - i);
sha256_final(&ctx, digest);
return (memcmp(digest, vector->digest, SHA256_DIGEST_LEN) == 0);
}
#endif
#ifdef BENCHMARKS
/*
* Performance test: measure the time spent computing the SHA256 sum of a
* message of the specified length.
*/
#define T_PERF_ITERATIONS 1000
static int
t_sha256_perf(char **desc, void *arg)
{
struct timespec ts, te;
unsigned long ns;
uint8_t digest[SHA256_DIGEST_LEN];
char *msg, *comment;
size_t msglen = *(size_t *)arg;
if ((msg = calloc(1, msglen)) == NULL)
err(1, "calloc()");
clock_gettime(CLOCK_MONOTONIC_PRECISE, &ts);
for (int i = 0; i < T_PERF_ITERATIONS; ++i)
t_sha256_complete(msg, msglen, digest);
clock_gettime(CLOCK_MONOTONIC_PRECISE, &te);
free(msg);
ns = te.tv_sec * 1000000000LU + te.tv_nsec;
ns -= ts.tv_sec * 1000000000LU + ts.tv_nsec;
asprintf(&comment, "%zu bytes: %d iterations in %'lu ns",
msglen, T_PERF_ITERATIONS, ns);
if (comment == NULL)
err(1, "asprintf()");
*desc = comment;
return (1);
}
#endif
/***************************************************************************
* Boilerplate
*/
int
t_prepare(int argc, char *argv[])
{
int i, n;
(void)argc;
(void)argv;
n = sizeof t_sha256_vectors / sizeof t_sha256_vectors[0];
for (i = 0; i < n; ++i)
t_add_test(t_sha256_vector, &t_sha256_vectors[i],
t_sha256_vectors[i].desc);
#if !defined(WITH_OPENSSL) && !defined(WITH_RSAREF)
/*
* Run test vector 5 (md5 test vector 7, which is 80 characters
* long) 5 characters at a time. This tests a) appending data to
* an underfull block and b) appending more data to an underfull
* block than it has room for (since 64 % 5 != 0). Test vector 4
* and 5 already exercised the code path for computing a block
* directly from source (without copying it in), and all the test
* vectors except vector 1 exercised the general case of copying a
* small amount of data in without crossing the block boundary.
*/
t_add_test(t_sha256_short_updates, &t_sha256_vectors[4],
"multiple short updates");
#endif
#ifdef BENCHMARKS
static size_t one = 1, thousand = 1000, million = 1000000;
t_add_test(t_sha256_perf, &one,
"performance test (1 byte)");
t_add_test(t_sha256_perf, &thousand,
"performance test (1,000 bytes)");
t_add_test(t_sha256_perf, &million,
"performance test (1,000,000 bytes)");
#endif
return (0);
}
void
t_cleanup(void)
{
}

286
t/t_sha384.c Normal file
View file

@ -0,0 +1,286 @@
/*-
* Copyright (c) 2012 Universitetet i Oslo
* Copyright (c) 2012-2014 Dag-Erling Smørgrav
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Cryb: trunk/t/t_sha384.c 3 2014-07-04 11:20:46Z des $
*/
#include "cryb/impl.h"
#include <err.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "t.h"
#if WITH_OPENSSL
#include <openssl/sha.h>
#define SHA384_DIGEST_LEN SHA384_DIGEST_LENGTH
static void
t_sha384_complete(const void *msg, size_t msglen, uint8_t *digest)
{
SHA512_CTX ctx; /* yes, 512 is correct */
SHA384_Init(&ctx);
SHA384_Update(&ctx, msg, msglen);
SHA384_Final(digest, &ctx);
}
#else
#include <cryb/sha384.h>
#define t_sha384_complete(msg, msglen, digest) \
sha384_complete(msg, msglen, digest)
#endif
static struct t_vector {
const char *desc;
const char *msg;
const uint8_t digest[SHA384_DIGEST_LEN];
} t_sha384_vectors[] = {
{
"zero-length message",
"",
{
0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38,
0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a,
0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43,
0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda,
0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb,
0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b,
}
},
{
"FIPS 180-2 D.1 (one-block message)",
"abc",
{
0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b,
0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07,
0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63,
0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed,
0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23,
0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7,
}
},
{
/*
* This message is *just* long enough to necessitate a
* second block, which consists entirely of padding.
*/
"FIPS 180-2 D.2 (multi-block message)",
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
{
0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8,
0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47,
0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2,
0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12,
0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9,
0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39,
}
},
{
/*
* 1,000,000 x 'a', filled in by t_prepare()
*/
"FIPS 180-2 D.3 (long message)",
NULL,
{
0x9d, 0x0e, 0x18, 0x09, 0x71, 0x64, 0x74, 0xcb,
0x08, 0x6e, 0x83, 0x4e, 0x31, 0x0a, 0x4a, 0x1c,
0xed, 0x14, 0x9e, 0x9c, 0x00, 0xf2, 0x48, 0x52,
0x79, 0x72, 0xce, 0xc5, 0x70, 0x4c, 0x2a, 0x5b,
0x07, 0xb8, 0xb3, 0xdc, 0x38, 0xec, 0xc4, 0xeb,
0xae, 0x97, 0xdd, 0xd8, 0x7f, 0x3d, 0x89, 0x85,
},
},
{
/*
* One of the MD5 test vectors, included for the "short
* update" test.
*/
"\"1234567890\"x8",
"1234567890123456789012345678901234567890"
"1234567890123456789012345678901234567890",
{
0xb1, 0x29, 0x32, 0xb0, 0x62, 0x7d, 0x1c, 0x06,
0x09, 0x42, 0xf5, 0x44, 0x77, 0x64, 0x15, 0x56,
0x55, 0xbd, 0x4d, 0xa0, 0xc9, 0xaf, 0xa6, 0xdd,
0x9b, 0x9e, 0xf5, 0x31, 0x29, 0xaf, 0x1b, 0x8f,
0xb0, 0x19, 0x59, 0x96, 0xd2, 0xde, 0x9c, 0xa0,
0xdf, 0x9d, 0x82, 0x1f, 0xfe, 0xe6, 0x70, 0x26,
},
},
};
/*
* Unit test: compute the SHA384 sum of the specified string and compare it
* to the expected result.
*/
static int
t_sha384_vector(char **desc CRYB_UNUSED, void *arg)
{
struct t_vector *vector = (struct t_vector *)arg;
uint8_t digest[SHA384_DIGEST_LEN];
char *msg;
if (vector->msg) {
t_sha384_complete(vector->msg, strlen(vector->msg), digest);
} else {
/* special case for FIPS test vector 3 */
if ((msg = malloc(1000000)) == NULL)
err(1, "malloc()");
memset(msg, 'a', 1000000);
t_sha384_complete(msg, 1000000, digest);
free(msg);
}
if (memcmp(digest, vector->digest, SHA384_DIGEST_LEN) != 0) {
t_verbose("expected ");
t_verbose_hex(vector->digest, SHA384_DIGEST_LEN);
t_verbose("\n");
t_verbose("got ");
t_verbose_hex(digest, SHA384_DIGEST_LEN);
t_verbose("\n");
return (0);
}
return (1);
}
#if !defined(WITH_OPENSSL) && !defined(WITH_RSAREF)
/*
* Various corner cases and error conditions
*/
static int
t_sha384_short_updates(char **desc CRYB_UNUSED, void *arg)
{
struct t_vector *vector = (struct t_vector *)arg;
uint8_t digest[SHA384_DIGEST_LEN];
sha384_ctx ctx;
int i, len;
sha384_init(&ctx);
len = strlen(vector->msg);
for (i = 0; i + 5 < len; i += 5)
sha384_update(&ctx, vector->msg + i, 5);
sha384_update(&ctx, vector->msg + i, len - i);
sha384_final(&ctx, digest);
return (memcmp(digest, vector->digest, SHA384_DIGEST_LEN) == 0);
}
#endif
#ifdef BENCHMARKS
/*
* Performance test: measure the time spent computing the SHA384 sum of a
* message of the specified length.
*/
#define T_PERF_ITERATIONS 1000
static int
t_sha384_perf(char **desc, void *arg)
{
struct timespec ts, te;
unsigned long ns;
uint8_t digest[SHA384_DIGEST_LEN];
char *msg, *comment;
size_t msglen = *(size_t *)arg;
if ((msg = calloc(1, msglen)) == NULL)
err(1, "calloc()");
clock_gettime(CLOCK_MONOTONIC_PRECISE, &ts);
for (int i = 0; i < T_PERF_ITERATIONS; ++i)
t_sha384_complete(msg, msglen, digest);
clock_gettime(CLOCK_MONOTONIC_PRECISE, &te);
free(msg);
ns = te.tv_sec * 1000000000LU + te.tv_nsec;
ns -= ts.tv_sec * 1000000000LU + ts.tv_nsec;
asprintf(&comment, "%zu bytes: %d iterations in %'lu ns",
msglen, T_PERF_ITERATIONS, ns);
if (comment == NULL)
err(1, "asprintf()");
*desc = comment;
return (1);
}
#endif
/***************************************************************************
* Boilerplate
*/
int
t_prepare(int argc, char *argv[])
{
int i, n;
(void)argc;
(void)argv;
n = sizeof t_sha384_vectors / sizeof t_sha384_vectors[0];
for (i = 0; i < n; ++i)
t_add_test(t_sha384_vector, &t_sha384_vectors[i],
t_sha384_vectors[i].desc);
#if !defined(WITH_OPENSSL) && !defined(WITH_RSAREF)
/*
* Run test vector 5 (md5 test vector 7, which is 80 characters
* long) 5 characters at a time. This tests a) appending data to
* an underfull block and b) appending more data to an underfull
* block than it has room for (since 64 % 5 != 0). Test vector 4
* and 5 already exercised the code path for computing a block
* directly from source (without copying it in), and all the test
* vectors except vector 1 exercised the general case of copying a
* small amount of data in without crossing the block boundary.
*/
t_add_test(t_sha384_short_updates, &t_sha384_vectors[4],
"multiple short updates");
#endif
#ifdef BENCHMARKS
static size_t one = 1, thousand = 1000, million = 1000000;
t_add_test(t_sha384_perf, &one,
"performance test (1 byte)");
t_add_test(t_sha384_perf, &thousand,
"performance test (1,000 bytes)");
t_add_test(t_sha384_perf, &million,
"performance test (1,000,000 bytes)");
#endif
return (0);
}
void
t_cleanup(void)
{
}

296
t/t_sha512.c Normal file
View file

@ -0,0 +1,296 @@
/*-
* Copyright (c) 2012 Universitetet i Oslo
* Copyright (c) 2012-2014 Dag-Erling Smørgrav
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Cryb$
*/
#include "cryb/impl.h"
#include <err.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "t.h"
#if WITH_OPENSSL
#include <openssl/sha.h>
#define SHA512_DIGEST_LEN SHA512_DIGEST_LENGTH
static void
t_sha512_complete(const void *msg, size_t msglen, uint8_t *digest)
{
SHA512_CTX ctx;
SHA512_Init(&ctx);
SHA512_Update(&ctx, msg, msglen);
SHA512_Final(digest, &ctx);
}
#else
#include <cryb/sha512.h>
#define t_sha512_complete(msg, msglen, digest) \
sha512_complete(msg, msglen, digest)
#endif
static struct t_vector {
const char *desc;
const char *msg;
const uint8_t digest[SHA512_DIGEST_LEN];
} t_sha512_vectors[] = {
{
"zero-length message",
"",
{
0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd,
0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07,
0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc,
0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce,
0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0,
0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f,
0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81,
0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e,
}
},
{
"FIPS 180-2 C.1 (one-block message)",
"abc",
{
0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,
0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f,
}
},
{
/*
* This message is *just* long enough to necessitate a
* second block, which consists entirely of padding.
*/
"FIPS 180-2 C.2 (multi-block message)",
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
{
0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,
0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,
0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,
0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,
0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,
0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,
0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09,
}
},
{
/*
* 1,000,000 x 'a', filled in by t_prepare()
*/
"FIPS 180-2 C.3 (long message)",
NULL,
{
0xe7, 0x18, 0x48, 0x3d, 0x0c, 0xe7, 0x69, 0x64,
0x4e, 0x2e, 0x42, 0xc7, 0xbc, 0x15, 0xb4, 0x63,
0x8e, 0x1f, 0x98, 0xb1, 0x3b, 0x20, 0x44, 0x28,
0x56, 0x32, 0xa8, 0x03, 0xaf, 0xa9, 0x73, 0xeb,
0xde, 0x0f, 0xf2, 0x44, 0x87, 0x7e, 0xa6, 0x0a,
0x4c, 0xb0, 0x43, 0x2c, 0xe5, 0x77, 0xc3, 0x1b,
0xeb, 0x00, 0x9c, 0x5c, 0x2c, 0x49, 0xaa, 0x2e,
0x4e, 0xad, 0xb2, 0x17, 0xad, 0x8c, 0xc0, 0x9b,
},
},
{
/*
* One of the MD5 test vectors, included for the "short
* update" test.
*/
"\"1234567890\"x8",
"1234567890123456789012345678901234567890"
"1234567890123456789012345678901234567890",
{
0x72, 0xec, 0x1e, 0xf1, 0x12, 0x4a, 0x45, 0xb0,
0x47, 0xe8, 0xb7, 0xc7, 0x5a, 0x93, 0x21, 0x95,
0x13, 0x5b, 0xb6, 0x1d, 0xe2, 0x4e, 0xc0, 0xd1,
0x91, 0x40, 0x42, 0x24, 0x6e, 0x0a, 0xec, 0x3a,
0x23, 0x54, 0xe0, 0x93, 0xd7, 0x6f, 0x30, 0x48,
0xb4, 0x56, 0x76, 0x43, 0x46, 0x90, 0x0c, 0xb1,
0x30, 0xd2, 0xa4, 0xfd, 0x5d, 0xd1, 0x6a, 0xbb,
0x5e, 0x30, 0xbc, 0xb8, 0x50, 0xde, 0xe8, 0x43,
},
},
};
/*
* Unit test: compute the SHA512 sum of the specified string and compare it
* to the expected result.
*/
static int
t_sha512_vector(char **desc CRYB_UNUSED, void *arg)
{
struct t_vector *vector = (struct t_vector *)arg;
uint8_t digest[SHA512_DIGEST_LEN];
char *msg;
if (vector->msg) {
t_sha512_complete(vector->msg, strlen(vector->msg), digest);
} else {
/* special case for FIPS test vector 3 */
if ((msg = malloc(1000000)) == NULL)
err(1, "malloc()");
memset(msg, 'a', 1000000);
t_sha512_complete(msg, 1000000, digest);
free(msg);
}
if (memcmp(digest, vector->digest, SHA512_DIGEST_LEN) != 0) {
t_verbose("expected ");
t_verbose_hex(vector->digest, SHA512_DIGEST_LEN);
t_verbose("\n");
t_verbose("got ");
t_verbose_hex(digest, SHA512_DIGEST_LEN);
t_verbose("\n");
return (0);
}
return (1);
}
#if !defined(WITH_OPENSSL) && !defined(WITH_RSAREF)
/*
* Various corner cases and error conditions
*/
static int
t_sha512_short_updates(char **desc CRYB_UNUSED, void *arg)
{
struct t_vector *vector = (struct t_vector *)arg;
uint8_t digest[SHA512_DIGEST_LEN];
sha512_ctx ctx;
int i, len;
sha512_init(&ctx);
len = strlen(vector->msg);
for (i = 0; i + 5 < len; i += 5)
sha512_update(&ctx, vector->msg + i, 5);
sha512_update(&ctx, vector->msg + i, len - i);
sha512_final(&ctx, digest);
return (memcmp(digest, vector->digest, SHA512_DIGEST_LEN) == 0);
}
#endif
#ifdef BENCHMARKS
/*
* Performance test: measure the time spent computing the SHA512 sum of a
* message of the specified length.
*/
#define T_PERF_ITERATIONS 1000
static int
t_sha512_perf(char **desc, void *arg)
{
struct timespec ts, te;
unsigned long ns;
uint8_t digest[SHA512_DIGEST_LEN];
char *msg, *comment;
size_t msglen = *(size_t *)arg;
if ((msg = calloc(1, msglen)) == NULL)
err(1, "calloc()");
clock_gettime(CLOCK_MONOTONIC_PRECISE, &ts);
for (int i = 0; i < T_PERF_ITERATIONS; ++i)
t_sha512_complete(msg, msglen, digest);
clock_gettime(CLOCK_MONOTONIC_PRECISE, &te);
free(msg);
ns = te.tv_sec * 1000000000LU + te.tv_nsec;
ns -= ts.tv_sec * 1000000000LU + ts.tv_nsec;
asprintf(&comment, "%zu bytes: %d iterations in %'lu ns",
msglen, T_PERF_ITERATIONS, ns);
if (comment == NULL)
err(1, "asprintf()");
*desc = comment;
return (1);
}
#endif
/***************************************************************************
* Boilerplate
*/
int
t_prepare(int argc, char *argv[])
{
int i, n;
(void)argc;
(void)argv;
n = sizeof t_sha512_vectors / sizeof t_sha512_vectors[0];
for (i = 0; i < n; ++i)
t_add_test(t_sha512_vector, &t_sha512_vectors[i],
t_sha512_vectors[i].desc);
#if !defined(WITH_OPENSSL) && !defined(WITH_RSAREF)
/*
* Run test vector 5 (md5 test vector 7, which is 80 characters
* long) 5 characters at a time. This tests a) appending data to
* an underfull block and b) appending more data to an underfull
* block than it has room for (since 64 % 5 != 0). Test vector 4
* and 5 already exercised the code path for computing a block
* directly from source (without copying it in), and all the test
* vectors except vector 1 exercised the general case of copying a
* small amount of data in without crossing the block boundary.
*/
t_add_test(t_sha512_short_updates, &t_sha512_vectors[4],
"multiple short updates");
#endif
#ifdef BENCHMARKS
static size_t one = 1, thousand = 1000, million = 1000000;
t_add_test(t_sha512_perf, &one,
"performance test (1 byte)");
t_add_test(t_sha512_perf, &thousand,
"performance test (1,000 bytes)");
t_add_test(t_sha512_perf, &million,
"performance test (1,000,000 bytes)");
#endif
return (0);
}
void
t_cleanup(void)
{
}