Major cleanup of the MD and SHA digests.

- Use the new vector byte-order conversion functions where appropriate.
- Use memset_s() instead of memset() where appropriate.
- Use consistent names and types for function arguments.
- Reindent, rename and reorganize to conform to Cryb style and idiom.

SHA224 and SHA256 were left mostly unchanged.  MD2 and MD4 were completely rewritten as the previous versions (taken from XySSL) seem to have been copied from RSAREF.

This breaks the ABI as some context structures have grown or shrunk and some function arguments have been changed from int to size_t.
This commit is contained in:
Dag-Erling Smørgrav 2017-03-20 00:13:47 +01:00
parent d96415b2c3
commit c6536641c5
18 changed files with 936 additions and 1392 deletions

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Christophe Devine * Copyright (c) 2014-2017 Dag-Erling Smørgrav
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -50,49 +50,17 @@ CRYB_BEGIN
extern digest_algorithm md2_digest; extern digest_algorithm md2_digest;
/** typedef struct {
* \brief MD2 context structure uint8_t state[48];
*/ uint8_t cksum[16];
typedef struct uint8_t block[16];
{ unsigned int blocklen;
uint8_t cksum[16]; /*!< checksum of the data block */
uint8_t state[48]; /*!< intermediate digest state */
uint8_t buffer[16]; /*!< data block being processed */
int left; /*!< amount of data in buffer */
} md2_ctx; } md2_ctx;
/** void md2_init(md2_ctx *);
* \brief MD2 context setup void md2_update(md2_ctx *, const void *, size_t);
* void md2_final(md2_ctx *, uint8_t *);
* \param ctx context to be initialized void md2_complete(const void *, size_t, uint8_t *);
*/
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, uint8_t *output );
/**
* \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, uint8_t *output );
CRYB_END CRYB_END

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Christophe Devine * Copyright (c) 2014-2017 Dag-Erling Smørgrav
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -50,57 +50,17 @@ CRYB_BEGIN
extern digest_algorithm md4_digest; extern digest_algorithm md4_digest;
/** typedef struct {
* \brief MD4 context structure uint8_t block[64];
*/ size_t blocklen;
typedef struct uint32_t state[4];
{ uint64_t bitlen;
uint64_t total; /*!< number of bytes processed */ } md4_ctx;
uint32_t state[4]; /*!< intermediate digest state */
uint8_t buffer[64]; /*!< data block being processed */
}
md4_ctx;
#ifdef __cplusplus void md4_init(md4_ctx *);
extern "C" { void md4_update(md4_ctx *, const void *, size_t);
#endif void md4_final(md4_ctx *, uint8_t *);
void md4_complete(const void *, size_t, uint8_t *);
/**
* \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, uint8_t *output );
/**
* \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, uint8_t *output );
#ifdef __cplusplus
}
#endif
CRYB_END CRYB_END

View file

@ -54,8 +54,8 @@ extern digest_algorithm md5_digest;
typedef struct { typedef struct {
uint8_t block[64]; uint8_t block[64];
size_t blocklen; size_t blocklen;
uint32_t state[4];
uint64_t bitlen; uint64_t bitlen;
uint32_t h[4];
} md5_ctx; } md5_ctx;
void md5_init(md5_ctx *); void md5_init(md5_ctx *);

View file

@ -52,10 +52,10 @@ CRYB_BEGIN
extern digest_algorithm sha1_digest; extern digest_algorithm sha1_digest;
typedef struct { typedef struct {
uint8_t block[64]; uint8_t block[64];
uint32_t blocklen; unsigned int blocklen;
uint32_t h[5]; uint32_t h[5];
uint64_t bitlen; uint64_t bitlen;
} sha1_ctx; } sha1_ctx;
void sha1_init(sha1_ctx *); void sha1_init(sha1_ctx *);

View file

@ -1,5 +1,6 @@
/*- /*-
* Copyright (c) 2005-2013 Colin Percival * Copyright (c) 2005-2013 Colin Percival
* Copyright (c) 2014-2017 Dag-Erling Smørgrav
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -10,6 +11,9 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@ -38,10 +42,6 @@ CRYB_BEGIN
#define SHA224_BLOCK_LEN 64 #define SHA224_BLOCK_LEN 64
#define SHA224_DIGEST_LEN 28 #define SHA224_DIGEST_LEN 28
/*
* Use #defines in order to avoid namespace collisions with anyone else's
* SHA224 code (e.g., the code in OpenSSL).
*/
#define sha224_digest cryb_sha224_digest #define sha224_digest cryb_sha224_digest
#define sha224_ctx cryb_sha224_ctx #define sha224_ctx cryb_sha224_ctx
#define sha224_init cryb_sha224_init #define sha224_init cryb_sha224_init
@ -51,46 +51,17 @@ CRYB_BEGIN
extern digest_algorithm sha224_digest; extern digest_algorithm sha224_digest;
/* Context structure for SHA224 operations. */
typedef struct { typedef struct {
uint32_t state[8]; uint32_t state[8];
uint64_t count; uint64_t count;
uint8_t buf[64]; uint8_t buf[64];
} sha224_ctx; } sha224_ctx;
/**
* sha224_init(ctx):
* Initialize the SHA224 context ${ctx}.
*/
void sha224_init(sha224_ctx *); void sha224_init(sha224_ctx *);
/**
* sha224_update(ctx, in, len):
* Input ${len} bytes from ${in} into the SHA224 context ${ctx}.
*/
void sha224_update(sha224_ctx *, const void *, size_t); void sha224_update(sha224_ctx *, const void *, size_t);
/**
* sha224_final(ctx, digest):
* Output the SHA224 hash of the data input to the context ${ctx} into the
* buffer ${digest}.
*/
void sha224_final(sha224_ctx *, uint8_t *); void sha224_final(sha224_ctx *, uint8_t *);
/**
* sha224_complete(in, len, digest):
* Compute the SHA224 hash of ${len} bytes from $in} and write it to ${digest}.
*/
void sha224_complete(const void *, size_t, uint8_t *); void sha224_complete(const void *, size_t, uint8_t *);
/**
* PBKDF2_SHA224(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
* Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA224 as the PRF, and
* write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
*/
void pbkdf2_sha224(const uint8_t *, size_t, const uint8_t *, size_t,
uint64_t, uint8_t *, size_t);
CRYB_END CRYB_END
#endif #endif

View file

@ -1,5 +1,6 @@
/*- /*-
* Copyright (c) 2005-2013 Colin Percival * Copyright (c) 2005-2013 Colin Percival
* Copyright (c) 2014-2017 Dag-Erling Smørgrav
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -10,6 +11,9 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@ -38,10 +42,6 @@ CRYB_BEGIN
#define SHA256_BLOCK_LEN 64 #define SHA256_BLOCK_LEN 64
#define SHA256_DIGEST_LEN 32 #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_digest cryb_sha256_digest
#define sha256_ctx cryb_sha256_ctx #define sha256_ctx cryb_sha256_ctx
#define sha256_init cryb_sha256_init #define sha256_init cryb_sha256_init
@ -51,46 +51,17 @@ CRYB_BEGIN
extern digest_algorithm sha256_digest; extern digest_algorithm sha256_digest;
/* Context structure for SHA256 operations. */
typedef struct { typedef struct {
uint32_t state[8]; uint32_t state[8];
uint64_t count; uint64_t count;
uint8_t buf[64]; uint8_t buf[64];
} sha256_ctx; } sha256_ctx;
/**
* sha256_init(ctx):
* Initialize the SHA256 context ${ctx}.
*/
void sha256_init(sha256_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); 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 *); void sha256_final(sha256_ctx *, uint8_t *);
/**
* 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 *); void sha256_complete(const void *, size_t, uint8_t *);
/**
* 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);
CRYB_END CRYB_END
#endif #endif

View file

@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2006-2007 Christophe Devine * Copyright (c) 2006-2007 Christophe Devine
* Copyright (c) 2017 Dag-Erling Smørgrav
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -50,49 +51,17 @@ CRYB_BEGIN
extern digest_algorithm sha384_digest; extern digest_algorithm sha384_digest;
/** typedef struct {
* \brief SHA-384 context structure uint8_t block[128];
*/ unsigned int blocklen;
typedef struct uint64_t h[8];
{ uint64_t bitlen[2];
uint64_t total[2]; /*!< number of bytes processed */ } sha384_ctx;
uint64_t state[8]; /*!< intermediate digest state */
uint8_t buffer[128]; /*!< data block being processed */
}
sha384_ctx;
/** void sha384_init(sha384_ctx *);
* \brief SHA-384 context setup void sha384_update(sha384_ctx *, const void *, size_t);
* void sha384_final(sha384_ctx *, uint8_t *);
* \param ctx context to be initialized void sha384_complete(const void *, size_t, uint8_t *);
*/
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, uint8_t *output );
/**
* \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, uint8_t *output );
CRYB_END CRYB_END

View file

@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2006-2007 Christophe Devine * Copyright (c) 2006-2007 Christophe Devine
* Copyright (c) 2017 Dag-Erling Smørgrav
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -50,49 +51,17 @@ CRYB_BEGIN
extern digest_algorithm sha512_digest; extern digest_algorithm sha512_digest;
/** typedef struct {
* \brief SHA-512 context structure uint8_t block[128];
*/ unsigned int blocklen;
typedef struct uint64_t h[8];
{ uint64_t bitlen[2];
uint64_t total[2]; /*!< number of bytes processed */ } sha512_ctx;
uint64_t state[8]; /*!< intermediate digest state */
uint8_t buffer[128]; /*!< data block being processed */
}
sha512_ctx;
/** void sha512_init(sha512_ctx *);
* \brief SHA-512 context setup void sha512_update(sha512_ctx *, const void *, size_t);
* void sha512_final(sha512_ctx *, uint8_t *);
* \param ctx context to be initialized void sha512_complete(const void *, size_t, uint8_t *);
*/
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, uint8_t *output );
/**
* \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, uint8_t *output );
CRYB_END CRYB_END

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Christophe Devine * Copyright (c) 2014-2017 Dag-Erling Smørgrav
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -26,153 +26,147 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
/*
* 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 "cryb/impl.h"
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <cryb/memset_s.h>
#include <cryb/md2.h> #include <cryb/md2.h>
static const uint8_t PI_SUBST[256] = /*
{ * MD2 - RFC 1319
0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, *
0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3, * Note 1: the pseudocode for the checksum calculation in the RFC contains
0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, * a significant error - consult the errata.
0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, *
0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E, * Note 2: the RFC describes the algorithm as having five steps: 1) append
0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, * padding, 2) compute checksum, 3) initialize state, 4) compute digest
0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, * and 5) output. This implementation merges the checksum and digest
0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21, * computations, which are independent of eachother, which avoids
0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, * processing the message twice. The padding is then appended and fed
0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3, * through the checksum and digest computation, and finally the checksum
0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, * itself is fed through. Note that we update the checksum *after* the
0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, * digest, otherwise the final step (mixing the checksum into the digest)
0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D, * would clobber the checksum before it was used.
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, static const uint8_t md2_s[256] = {
0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, 0x29, 0x2e, 0x43, 0xc9, 0xa2, 0xd8, 0x7c, 0x01,
0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E, 0x3d, 0x36, 0x54, 0xa1, 0xec, 0xf0, 0x06, 0x13,
0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 0x62, 0xa7, 0x05, 0xf3, 0xc0, 0xc7, 0x73, 0x8c,
0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, 0x98, 0x93, 0x2b, 0xd9, 0xbc, 0x4c, 0x82, 0xca,
0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88, 0x1e, 0x9b, 0x57, 0x3c, 0xfd, 0xd4, 0xe0, 0x16,
0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, 0x67, 0x42, 0x6f, 0x18, 0x8a, 0x17, 0xe5, 0x12,
0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, 0xbe, 0x4e, 0xc4, 0xd6, 0xda, 0x9e, 0xde, 0x49,
0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A, 0xa0, 0xfb, 0xf5, 0x8e, 0xbb, 0x2f, 0xee, 0x7a,
0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, 0xa9, 0x68, 0x79, 0x91, 0x15, 0xb2, 0x07, 0x3f,
0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14 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,
}; };
/* void
* MD2 context setup md2_init(md2_ctx *ctx)
*/
void md2_init( md2_ctx *ctx )
{ {
memset( ctx, 0, sizeof( md2_ctx ) );
memset(ctx, 0, sizeof *ctx);
} }
static void md2_process( md2_ctx *ctx ) static void
md2_compute(md2_ctx *ctx, const uint8_t *block)
{ {
int i, j; unsigned int j, k;
uint8_t t = 0; uint8_t l, t;
for( i = 0; i < 16; i++ ) for (j = 0; j < 16; j++) {
{ ctx->state[j + 16] = block[j];
ctx->state[i + 16] = ctx->buffer[i]; ctx->state[j + 32] = block[j] ^ ctx->state[j];
ctx->state[i + 32] =
(uint8_t)( ctx->buffer[i] ^ ctx->state[i]);
}
for( i = 0; i < 18; i++ )
{
for( j = 0; j < 48; j++ )
{
ctx->state[j] = (uint8_t)
( ctx->state[j] ^ PI_SUBST[t] );
t = ctx->state[j];
} }
t = 0;
t = (uint8_t)( t + i ); for (j = 0; j < 18; ++j) {
} for (k = 0; k < 48; ++k) {
ctx->state[k] = ctx->state[k] ^ md2_s[t];
t = ctx->cksum[15]; t = ctx->state[k];
}
for( i = 0; i < 16; i++ ) t = t + j;
{ }
ctx->cksum[i] = (uint8_t) l = ctx->cksum[15];
( ctx->cksum[i] ^ PI_SUBST[ctx->buffer[i] ^ t] ); for (j = 0; j < 16; ++j) {
t = ctx->cksum[i]; ctx->cksum[j] ^= md2_s[block[j] ^ l];
} l = ctx->cksum[j];
}
/*
* 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 );
} }
}
} }
/* void
* MD2 final digest md2_update(md2_ctx *ctx, const void *buf, size_t len)
*/
void md2_final( md2_ctx *ctx, uint8_t *output )
{ {
int i; size_t copylen;
uint8_t x;
x = (uint8_t)( 16 - ctx->left ); while (len) {
if (ctx->blocklen > 0 || len < sizeof ctx->block) {
for( i = ctx->left; i < 16; i++ ) copylen = sizeof ctx->block - ctx->blocklen;
ctx->buffer[i] = x; if (copylen > len)
copylen = len;
md2_process( ctx ); memcpy(ctx->block + ctx->blocklen, buf, copylen);
ctx->blocklen += copylen;
memcpy( ctx->buffer, ctx->cksum, sizeof ctx->cksum ); if (ctx->blocklen == sizeof ctx->block) {
md2_process( ctx ); md2_compute(ctx, ctx->block);
ctx->blocklen = 0;
memcpy( output, ctx->state, MD2_DIGEST_LEN ); }
} else {
copylen = sizeof ctx->block;
md2_compute(ctx, buf);
}
buf += copylen;
len -= copylen;
}
} }
/* void
* output = MD2( input buffer ) md2_final(md2_ctx *ctx, uint8_t *digest)
*/
void md2_complete( const void *input, int ilen, uint8_t *output )
{ {
md2_ctx ctx; unsigned int i;
uint8_t x;
md2_init( &ctx ); x = sizeof ctx->block - ctx->blocklen;
md2_update( &ctx, input, ilen ); for (i = ctx->blocklen; i < sizeof ctx->block; i++)
md2_final( &ctx, output ); ctx->block[i] = x;
md2_compute(ctx, ctx->block);
md2_compute(ctx, ctx->cksum);
memcpy(digest, ctx->state, MD2_DIGEST_LEN);
memset_s(&ctx, 0, sizeof ctx, sizeof ctx);
}
memset( &ctx, 0, sizeof( md2_ctx ) ); void md2_complete(const void *buf, size_t len, uint8_t *digest)
{
md2_ctx ctx;
md2_init(&ctx);
md2_update(&ctx, buf, len);
md2_final(&ctx, digest);
} }
digest_algorithm md2_digest = { digest_algorithm md2_digest = {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Christophe Devine * Copyright (c) 2014-2017 Dag-Erling Smørgrav
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -26,217 +26,169 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
/*
* 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 "cryb/impl.h"
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <cryb/bitwise.h>
#include <cryb/endian.h> #include <cryb/endian.h>
#include <cryb/memset_s.h>
#include <cryb/md4.h> #include <cryb/md4.h>
/* /*
* MD4 context setup * MD4 - RFC 1320
*/ */
void md4_init( md4_ctx *ctx )
{
ctx->total = 0;
ctx->state[0] = 0x67452301; /* initial state */
ctx->state[1] = 0xEFCDAB89; static const uint32_t md4_h[4] = {
ctx->state[2] = 0x98BADCFE; 0x67452301UL, 0xefcdab89UL, 0x98badcfeUL, 0x10325476UL,
ctx->state[3] = 0x10325476;
}
static void md4_process( md4_ctx *ctx, const uint8_t *data )
{
uint32_t X[16], A, B, C, D;
X[ 0] = le32dec(data + 0);
X[ 1] = le32dec(data + 4);
X[ 2] = le32dec(data + 8);
X[ 3] = le32dec(data + 12);
X[ 4] = le32dec(data + 16);
X[ 5] = le32dec(data + 20);
X[ 6] = le32dec(data + 24);
X[ 7] = le32dec(data + 28);
X[ 8] = le32dec(data + 32);
X[ 9] = le32dec(data + 36);
X[10] = le32dec(data + 40);
X[11] = le32dec(data + 44);
X[12] = le32dec(data + 48);
X[13] = le32dec(data + 52);
X[14] = le32dec(data + 56);
X[15] = le32dec(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;
uint32_t left;
if( ilen <= 0 )
return;
left = ctx->total & 0x3F;
fill = 64 - left;
ctx->total += ilen;
if( left && ilen >= fill )
{
memcpy( (ctx->buffer + left), 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( (ctx->buffer + left), input, ilen );
}
}
static const uint8_t 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
}; };
/* void
* MD4 final digest md4_init(md4_ctx *ctx)
*/
void md4_final( md4_ctx *ctx, uint8_t *output )
{ {
uint32_t last, padn;
uint8_t msglen[8];
le64enc(msglen, ctx->total << 3); memset(ctx, 0, sizeof *ctx);
memcpy(ctx->state, md4_h, sizeof ctx->state);
last = ctx->total & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
md4_update( ctx, md4_padding, padn );
md4_update( ctx, msglen, 8 );
le32enc(output + 0, ctx->state[0]);
le32enc(output + 4, ctx->state[1]);
le32enc(output + 8, ctx->state[2]);
le32enc(output + 12, ctx->state[3]);
} }
/* static void
* output = MD4( input buffer ) md4_compute(md4_ctx *ctx, const uint8_t *data)
*/
void md4_complete( const void *input, int ilen, uint8_t *output )
{ {
md4_ctx ctx; uint32_t X[16];
uint32_t A, B, C, D;
md4_init( &ctx ); le32decv(X, data, 16);
md4_update( &ctx, input, ilen );
md4_final( &ctx, output );
memset( &ctx, 0, sizeof( md4_ctx ) ); 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 md4_round1(a, b, c, d, k, s) \
a = rol32(a + F(b, c, d) + X[k], s)
#define G(x, y, z) (x & y | x & z | y & z)
#define md4_round2(a, b, c, d, k, s) \
a = rol32(a + G(b, c, d) + X[k] + 0x5a827999, s)
#define H(x, y, z) (x ^ y ^ z)
#define md4_round3(a, b, c, d, k, s) \
a = rol32(a + H(b,c,d) + X[k] + 0x6ed9eba1, s)
md4_round1(A, B, C, D, 0, 3);
md4_round1(D, A, B, C, 1, 7);
md4_round1(C, D, A, B, 2, 11);
md4_round1(B, C, D, A, 3, 19);
md4_round1(A, B, C, D, 4, 3);
md4_round1(D, A, B, C, 5, 7);
md4_round1(C, D, A, B, 6, 11);
md4_round1(B, C, D, A, 7, 19);
md4_round1(A, B, C, D, 8, 3);
md4_round1(D, A, B, C, 9, 7);
md4_round1(C, D, A, B, 10, 11);
md4_round1(B, C, D, A, 11, 19);
md4_round1(A, B, C, D, 12, 3);
md4_round1(D, A, B, C, 13, 7);
md4_round1(C, D, A, B, 14, 11);
md4_round1(B, C, D, A, 15, 19);
md4_round2(A, B, C, D, 0, 3);
md4_round2(D, A, B, C, 4, 5);
md4_round2(C, D, A, B, 8, 9);
md4_round2(B, C, D, A, 12, 13);
md4_round2(A, B, C, D, 1, 3);
md4_round2(D, A, B, C, 5, 5);
md4_round2(C, D, A, B, 9, 9);
md4_round2(B, C, D, A, 13, 13);
md4_round2(A, B, C, D, 2, 3);
md4_round2(D, A, B, C, 6, 5);
md4_round2(C, D, A, B, 10, 9);
md4_round2(B, C, D, A, 14, 13);
md4_round2(A, B, C, D, 3, 3);
md4_round2(D, A, B, C, 7, 5);
md4_round2(C, D, A, B, 11, 9);
md4_round2(B, C, D, A, 15, 13);
md4_round3(A, B, C, D, 0, 3);
md4_round3(D, A, B, C, 8, 9);
md4_round3(C, D, A, B, 4, 11);
md4_round3(B, C, D, A, 12, 15);
md4_round3(A, B, C, D, 2, 3);
md4_round3(D, A, B, C, 10, 9);
md4_round3(C, D, A, B, 6, 11);
md4_round3(B, C, D, A, 14, 15);
md4_round3(A, B, C, D, 1, 3);
md4_round3(D, A, B, C, 9, 9);
md4_round3(C, D, A, B, 5, 11);
md4_round3(B, C, D, A, 13, 15);
md4_round3(A, B, C, D, 3, 3);
md4_round3(D, A, B, C, 11, 9);
md4_round3(C, D, A, B, 7, 11);
md4_round3(B, C, D, A, 15, 15);
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
}
void
md4_update(md4_ctx *ctx, const void *buf, size_t len)
{
size_t copylen;
while (len) {
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 == sizeof ctx->block) {
md4_compute(ctx, ctx->block);
ctx->blocklen = 0;
}
} else {
copylen = sizeof ctx->block;
md4_compute(ctx, buf);
}
ctx->bitlen += copylen * 8;
buf += copylen;
len -= copylen;
}
}
void
md4_final(md4_ctx *ctx, uint8_t *digest)
{
ctx->block[ctx->blocklen++] = 0x80;
memset(ctx->block + ctx->blocklen, 0,
sizeof ctx->block - ctx->blocklen);
if (ctx->blocklen > 56) {
md4_compute(ctx, ctx->block);
ctx->blocklen = 0;
memset(ctx->block, 0, sizeof ctx->block);
}
le64enc(ctx->block + 56, ctx->bitlen);
md4_compute(ctx, ctx->block);
le32encv(digest, ctx->state, 4);
memset_s(ctx, 0, sizeof *ctx, sizeof *ctx);
}
void
md4_complete(const void *buf, size_t len, uint8_t *digest)
{
md4_ctx ctx;
md4_init(&ctx);
md4_update(&ctx, buf, len);
md4_final(&ctx, digest);
} }
digest_algorithm md4_digest = { digest_algorithm md4_digest = {

View file

@ -35,30 +35,36 @@
#include <cryb/bitwise.h> #include <cryb/bitwise.h>
#include <cryb/endian.h> #include <cryb/endian.h>
#include <cryb/memset_s.h>
#include <cryb/md5.h> #include <cryb/md5.h>
/*
* MD5 - RFC 1321
*/
/* initial state */ /* initial state */
static const uint32_t md5_h[4] = { static const uint32_t md5_h[4] = {
0x67452301U, 0xefcdab89U, 0x98badcfeU, 0x10325476U, 0x67452301UL, 0xefcdab89UL, 0x98badcfeUL, 0x10325476UL,
}; };
static const uint32_t md5_k[64] = { static const uint32_t md5_k[64] = {
0xd76aa478U, 0xe8c7b756U, 0x242070dbU, 0xc1bdceeeU, 0xd76aa478UL, 0xe8c7b756UL, 0x242070dbUL, 0xc1bdceeeUL,
0xf57c0fafU, 0x4787c62aU, 0xa8304613U, 0xfd469501U, 0xf57c0fafUL, 0x4787c62aUL, 0xa8304613UL, 0xfd469501UL,
0x698098d8U, 0x8b44f7afU, 0xffff5bb1U, 0x895cd7beU, 0x698098d8UL, 0x8b44f7afUL, 0xffff5bb1UL, 0x895cd7beUL,
0x6b901122U, 0xfd987193U, 0xa679438eU, 0x49b40821U, 0x6b901122UL, 0xfd987193UL, 0xa679438eUL, 0x49b40821UL,
0xf61e2562U, 0xc040b340U, 0x265e5a51U, 0xe9b6c7aaU, 0xf61e2562UL, 0xc040b340UL, 0x265e5a51UL, 0xe9b6c7aaUL,
0xd62f105dU, 0x02441453U, 0xd8a1e681U, 0xe7d3fbc8U, 0xd62f105dUL, 0x02441453UL, 0xd8a1e681UL, 0xe7d3fbc8UL,
0x21e1cde6U, 0xc33707d6U, 0xf4d50d87U, 0x455a14edU, 0x21e1cde6UL, 0xc33707d6UL, 0xf4d50d87UL, 0x455a14edUL,
0xa9e3e905U, 0xfcefa3f8U, 0x676f02d9U, 0x8d2a4c8aU, 0xa9e3e905UL, 0xfcefa3f8UL, 0x676f02d9UL, 0x8d2a4c8aUL,
0xfffa3942U, 0x8771f681U, 0x6d9d6122U, 0xfde5380cU, 0xfffa3942UL, 0x8771f681UL, 0x6d9d6122UL, 0xfde5380cUL,
0xa4beea44U, 0x4bdecfa9U, 0xf6bb4b60U, 0xbebfbc70U, 0xa4beea44UL, 0x4bdecfa9UL, 0xf6bb4b60UL, 0xbebfbc70UL,
0x289b7ec6U, 0xeaa127faU, 0xd4ef3085U, 0x04881d05U, 0x289b7ec6UL, 0xeaa127faUL, 0xd4ef3085UL, 0x04881d05UL,
0xd9d4d039U, 0xe6db99e5U, 0x1fa27cf8U, 0xc4ac5665U, 0xd9d4d039UL, 0xe6db99e5UL, 0x1fa27cf8UL, 0xc4ac5665UL,
0xf4292244U, 0x432aff97U, 0xab9423a7U, 0xfc93a039U, 0xf4292244UL, 0x432aff97UL, 0xab9423a7UL, 0xfc93a039UL,
0x655b59c3U, 0x8f0ccc92U, 0xffeff47dU, 0x85845dd1U, 0x655b59c3UL, 0x8f0ccc92UL, 0xffeff47dUL, 0x85845dd1UL,
0x6fa87e4fU, 0xfe2ce6e0U, 0xa3014314U, 0x4e0811a1U, 0x6fa87e4fUL, 0xfe2ce6e0UL, 0xa3014314UL, 0x4e0811a1UL,
0xf7537e82U, 0xbd3af235U, 0x2ad7d2bbU, 0xeb86d391U, 0xf7537e82UL, 0xbd3af235UL, 0x2ad7d2bbUL, 0xeb86d391UL,
}; };
void void
@ -66,7 +72,7 @@ md5_init(md5_ctx *ctx)
{ {
memset(ctx, 0, sizeof *ctx); memset(ctx, 0, sizeof *ctx);
memcpy(ctx->h, md5_h, sizeof ctx->h); memcpy(ctx->state, md5_h, sizeof ctx->state);
} }
#define md5_f(i, a, b, c, d, x, s) do { \ #define md5_f(i, a, b, c, d, x, s) do { \
@ -98,13 +104,11 @@ md5_compute(md5_ctx *ctx, const uint8_t *block)
{ {
uint32_t w[16], a, b, c, d; uint32_t w[16], a, b, c, d;
memcpy(w, block, 64); le32decv(w, block, 16);
for (int i = 0; i < 16; ++i) a = ctx->state[0];
w[i] = le32toh(w[i]); b = ctx->state[1];
a = ctx->h[0]; c = ctx->state[2];
b = ctx->h[1]; d = ctx->state[3];
c = ctx->h[2];
d = ctx->h[3];
md5_f( 0, a, b, c, d, w, 7); md5_f( 0, a, b, c, d, w, 7);
md5_f( 1, d, a, b, c, w, 12); md5_f( 1, d, a, b, c, w, 12);
@ -174,10 +178,10 @@ md5_compute(md5_ctx *ctx, const uint8_t *block)
md5_i(62, c, d, a, b, w, 15); md5_i(62, c, d, a, b, w, 15);
md5_i(63, b, c, d, a, w, 21); md5_i(63, b, c, d, a, w, 21);
ctx->h[0] += a; ctx->state[0] += a;
ctx->h[1] += b; ctx->state[1] += b;
ctx->h[2] += c; ctx->state[2] += c;
ctx->h[3] += d; ctx->state[3] += d;
} }
void void
@ -195,7 +199,6 @@ md5_update(md5_ctx *ctx, const void *buf, size_t len)
if (ctx->blocklen == sizeof ctx->block) { if (ctx->blocklen == sizeof ctx->block) {
md5_compute(ctx, ctx->block); md5_compute(ctx, ctx->block);
ctx->blocklen = 0; ctx->blocklen = 0;
memset(ctx->block, 0, sizeof ctx->block);
} }
} else { } else {
copylen = sizeof ctx->block; copylen = sizeof ctx->block;
@ -212,19 +215,17 @@ md5_final(md5_ctx *ctx, uint8_t *digest)
{ {
ctx->block[ctx->blocklen++] = 0x80; ctx->block[ctx->blocklen++] = 0x80;
memset(ctx->block + ctx->blocklen, 0,
sizeof ctx->block - ctx->blocklen);
if (ctx->blocklen > 56) { if (ctx->blocklen > 56) {
md5_compute(ctx, ctx->block); md5_compute(ctx, ctx->block);
ctx->blocklen = 0; ctx->blocklen = 0;
memset(ctx->block, 0, sizeof ctx->block); memset(ctx->block, 0, sizeof ctx->block);
} }
le32enc(ctx->block + 56, ctx->bitlen & 0xffffffffUL); le64enc(ctx->block + 56, ctx->bitlen);
le32enc(ctx->block + 60, ctx->bitlen >> 32);
md5_compute(ctx, ctx->block); md5_compute(ctx, ctx->block);
le32enc(digest, ctx->h[0]); le32encv(digest, ctx->state, 4);
le32enc(digest + 4, ctx->h[1]); memset_s(ctx, 0, sizeof *ctx, sizeof *ctx);
le32enc(digest + 8, ctx->h[2]);
le32enc(digest + 12, ctx->h[3]);
memset(ctx, 0, sizeof *ctx);
} }
void void

View file

@ -35,6 +35,8 @@
#include <cryb/bitwise.h> #include <cryb/bitwise.h>
#include <cryb/endian.h> #include <cryb/endian.h>
#include <cryb/memset_s.h>
#include <cryb/sha1.h> #include <cryb/sha1.h>
static uint32_t sha1_h[5] = { static uint32_t sha1_h[5] = {
@ -70,11 +72,10 @@ static void
sha1_compute(sha1_ctx *ctx, const uint8_t *block) sha1_compute(sha1_ctx *ctx, const uint8_t *block)
{ {
uint32_t w[80], a, b, c, d, e; uint32_t w[80], a, b, c, d, e;
unsigned int i;
memcpy(w, block, 64); be32decv(w, block, 16);
for (int i = 0; i < 16; ++i) for (i = 16; i < 80; ++i) {
w[i] = be32toh(w[i]);
for (int i = 16; i < 80; ++i) {
w[i] = w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]; w[i] = w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16];
w[i] = rol32(w[i], 1); w[i] = rol32(w[i], 1);
} }
@ -190,7 +191,6 @@ sha1_update(sha1_ctx *ctx, const void *buf, size_t len)
if (ctx->blocklen == sizeof ctx->block) { if (ctx->blocklen == sizeof ctx->block) {
sha1_compute(ctx, ctx->block); sha1_compute(ctx, ctx->block);
ctx->blocklen = 0; ctx->blocklen = 0;
memset(ctx->block, 0, sizeof ctx->block);
} }
} else { } else {
copylen = sizeof ctx->block; copylen = sizeof ctx->block;
@ -205,24 +205,19 @@ sha1_update(sha1_ctx *ctx, const void *buf, size_t len)
void void
sha1_final(sha1_ctx *ctx, uint8_t *digest) sha1_final(sha1_ctx *ctx, uint8_t *digest)
{ {
uint32_t hi, lo;
ctx->block[ctx->blocklen++] = 0x80; ctx->block[ctx->blocklen++] = 0x80;
memset(ctx->block + ctx->blocklen, 0,
sizeof ctx->block - ctx->blocklen);
if (ctx->blocklen > 56) { if (ctx->blocklen > 56) {
sha1_compute(ctx, ctx->block); sha1_compute(ctx, ctx->block);
ctx->blocklen = 0; ctx->blocklen = 0;
memset(ctx->block, 0, sizeof ctx->block); memset(ctx->block, 0, sizeof ctx->block);
} }
hi = htobe32(ctx->bitlen >> 32); be64enc(ctx->block + 56, ctx->bitlen);
lo = htobe32(ctx->bitlen & 0xffffffffUL);
memcpy(ctx->block + 56, &hi, 4);
memcpy(ctx->block + 60, &lo, 4);
ctx->blocklen = 64;
sha1_compute(ctx, ctx->block); sha1_compute(ctx, ctx->block);
for (int i = 0; i < 5; ++i) be32encv(digest, ctx->h, 5);
ctx->h[i] = htobe32(ctx->h[i]); memset_s(ctx, 0, sizeof *ctx, sizeof *ctx);
memcpy(digest, ctx->h, 20);
memset(ctx, 0, sizeof *ctx);
} }
void void

View file

@ -1,5 +1,6 @@
/*- /*-
* Copyright (c) 2005-2013 Colin Percival * Copyright (c) 2005-2013 Colin Percival
* Copyright (c) 2017 Dag-Erling Smørgrav
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -10,6 +11,9 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@ -29,44 +33,20 @@
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <cryb/bitwise.h>
#include <cryb/endian.h> #include <cryb/endian.h>
#include <cryb/memset_s.h>
#include <cryb/sha224.h> #include <cryb/sha224.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 SHA224 */ /* Elementary functions used by SHA224 */
#define Ch(x, y, z) ((x & (y ^ z)) ^ z) #define Ch(x, y, z) ((x & (y ^ z)) ^ z)
#define Maj(x, y, z) ((x & (y | z)) | (y & z)) #define Maj(x, y, z) ((x & (y | z)) | (y & z))
#define SHR(x, n) (x >> n) #define SHR(x, n) (x >> n)
#define ROTR(x, n) ((x >> n) | (x << (32 - n))) #define S0(x) (ror32(x, 2) ^ ror32(x, 13) ^ ror32(x, 22))
#define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) #define S1(x) (ror32(x, 6) ^ ror32(x, 11) ^ ror32(x, 25))
#define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) #define s0(x) (ror32(x, 7) ^ ror32(x, 18) ^ (x >> 3))
#define s0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3)) #define s1(x) (ror32(x, 17) ^ ror32(x, 19) ^ (x >> 10))
#define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10))
/* SHA224 round function */ /* SHA224 round function */
#define RND(a, b, c, d, e, f, g, h, k) \ #define RND(a, b, c, d, e, f, g, h, k) \
@ -88,7 +68,7 @@ be32dec_vect(uint32_t *dst, const uint8_t *src, size_t len)
* the 512-bit input block to produce a new state. * the 512-bit input block to produce a new state.
*/ */
static void static void
sha224_Transform(uint32_t * state, const uint8_t block[64]) sha224_Transform(uint32_t *state, const uint8_t block[64])
{ {
uint32_t W[64]; uint32_t W[64];
uint32_t S[8]; uint32_t S[8];
@ -96,7 +76,7 @@ sha224_Transform(uint32_t * state, const uint8_t block[64])
int i; int i;
/* 1. Prepare message schedule W. */ /* 1. Prepare message schedule W. */
be32dec_vect(W, block, 64); be32decv(W, block, 16);
for (i = 16; i < 64; i++) for (i = 16; i < 64; i++)
W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16]; W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16];
@ -104,16 +84,16 @@ sha224_Transform(uint32_t * state, const uint8_t block[64])
memcpy(S, state, 32); memcpy(S, state, 32);
/* 3. Mix. */ /* 3. Mix. */
RNDr(S, W, 0, 0x428a2f98); RNDr(S, W, 0, 0x428a2f98);
RNDr(S, W, 1, 0x71374491); RNDr(S, W, 1, 0x71374491);
RNDr(S, W, 2, 0xb5c0fbcf); RNDr(S, W, 2, 0xb5c0fbcf);
RNDr(S, W, 3, 0xe9b5dba5); RNDr(S, W, 3, 0xe9b5dba5);
RNDr(S, W, 4, 0x3956c25b); RNDr(S, W, 4, 0x3956c25b);
RNDr(S, W, 5, 0x59f111f1); RNDr(S, W, 5, 0x59f111f1);
RNDr(S, W, 6, 0x923f82a4); RNDr(S, W, 6, 0x923f82a4);
RNDr(S, W, 7, 0xab1c5ed5); RNDr(S, W, 7, 0xab1c5ed5);
RNDr(S, W, 8, 0xd807aa98); RNDr(S, W, 8, 0xd807aa98);
RNDr(S, W, 9, 0x12835b01); RNDr(S, W, 9, 0x12835b01);
RNDr(S, W, 10, 0x243185be); RNDr(S, W, 10, 0x243185be);
RNDr(S, W, 11, 0x550c7dc3); RNDr(S, W, 11, 0x550c7dc3);
RNDr(S, W, 12, 0x72be5d74); RNDr(S, W, 12, 0x72be5d74);
@ -172,23 +152,22 @@ sha224_Transform(uint32_t * state, const uint8_t block[64])
/* 4. Mix local working variables into global state. */ /* 4. Mix local working variables into global state. */
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
state[i] += S[i]; state[i] += S[i];
/* Clean the stack. */
memset(W, 0, 256);
memset(S, 0, 32);
t0 = t1 = 0;
} }
static uint8_t PAD[64] = { static uint8_t PAD[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
}; };
/* Add padding and terminating bit-count. */ /* Add padding and terminating bit-count. */
static void static void
sha224_pad(sha224_ctx * ctx) sha224_pad(sha224_ctx *ctx)
{ {
uint8_t len[8]; uint8_t len[8];
uint32_t r, plen; uint32_t r, plen;
@ -213,7 +192,7 @@ sha224_pad(sha224_ctx * ctx)
* Initialize the SHA224 context ${ctx}. * Initialize the SHA224 context ${ctx}.
*/ */
void void
sha224_init(sha224_ctx * ctx) sha224_init(sha224_ctx *ctx)
{ {
/* Zero bits processed so far. */ /* Zero bits processed so far. */
@ -235,7 +214,7 @@ sha224_init(sha224_ctx * ctx)
* Input ${len} bytes from ${in} into the SHA224 context ${ctx}. * Input ${len} bytes from ${in} into the SHA224 context ${ctx}.
*/ */
void void
sha224_update(sha224_ctx * ctx, const void *in, size_t len) sha224_update(sha224_ctx *ctx, const void *in, size_t len)
{ {
uint32_t r; uint32_t r;
const uint8_t *src = in; const uint8_t *src = in;
@ -279,17 +258,17 @@ sha224_update(sha224_ctx * ctx, const void *in, size_t len)
* buffer ${digest}. * buffer ${digest}.
*/ */
void void
sha224_final(sha224_ctx * ctx, uint8_t *digest) sha224_final(sha224_ctx *ctx, uint8_t *digest)
{ {
/* Add padding. */ /* Add padding. */
sha224_pad(ctx); sha224_pad(ctx);
/* Write the hash. */ /* Write the hash. */
be32enc_vect(digest, ctx->state, SHA224_DIGEST_LEN); be32encv(digest, ctx->state, SHA224_DIGEST_LEN / 4);
/* Clear the context state. */ /* Clear the context state. */
memset(ctx, 0, sizeof(*ctx)); memset_s(ctx, 0, sizeof *ctx, sizeof *ctx);
} }
/** /**
@ -297,7 +276,7 @@ sha224_final(sha224_ctx * ctx, uint8_t *digest)
* Compute the SHA224 hash of ${len} bytes from $in} and write it to ${digest}. * Compute the SHA224 hash of ${len} bytes from $in} and write it to ${digest}.
*/ */
void void
sha224_complete(const void * in, size_t len, uint8_t *digest) sha224_complete(const void *in, size_t len, uint8_t *digest)
{ {
sha224_ctx ctx; sha224_ctx ctx;
@ -306,65 +285,6 @@ sha224_complete(const void * in, size_t len, uint8_t *digest)
sha224_final(&ctx, digest); sha224_final(&ctx, digest);
} }
#if 0
/**
* PBKDF2_SHA224(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
* Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA224 as the PRF, and
* write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
*/
void
pbkdf2_sha224(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt,
size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen)
{
hmac_sha224_ctx PShctx, hctx;
size_t i;
uint8_t ivec[4];
uint8_t U[SHA224_DIGEST_LEN];
uint8_t T[SHA224_DIGEST_LEN];
uint64_t j;
unsigned int k;
size_t clen;
/* Compute HMAC state after processing P and S. */
hmac_sha224_init(&PShctx, passwd, passwdlen);
hmac_sha224_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_sha224_ctx));
hmac_sha224_update(&hctx, ivec, 4);
hmac_sha224_final(&hctx, U);
/* T_i = U_1 ... */
memcpy(T, U, sizeof T);
for (j = 2; j <= c; j++) {
/* Compute U_j. */
hmac_sha224_init(&hctx, passwd, passwdlen);
hmac_sha224_update(&hctx, U, 32);
hmac_sha224_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_sha224_ctx));
}
#endif
digest_algorithm sha224_digest = { digest_algorithm sha224_digest = {
.name = "sha224", .name = "sha224",
.contextlen = sizeof(sha224_ctx), .contextlen = sizeof(sha224_ctx),

View file

@ -1,5 +1,6 @@
/*- /*-
* Copyright (c) 2005-2013 Colin Percival * Copyright (c) 2005-2013 Colin Percival
* Copyright (c) 2017 Dag-Erling Smørgrav
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -10,6 +11,9 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@ -29,44 +33,19 @@
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <cryb/bitwise.h>
#include <cryb/endian.h> #include <cryb/endian.h>
#include <cryb/memset_s.h>
#include <cryb/sha256.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 */ /* Elementary functions used by SHA256 */
#define Ch(x, y, z) ((x & (y ^ z)) ^ z) #define Ch(x, y, z) ((x & (y ^ z)) ^ z)
#define Maj(x, y, z) ((x & (y | z)) | (y & z)) #define Maj(x, y, z) ((x & (y | z)) | (y & z))
#define SHR(x, n) (x >> n) #define S0(x) (ror32(x, 2) ^ ror32(x, 13) ^ ror32(x, 22))
#define ROTR(x, n) ((x >> n) | (x << (32 - n))) #define S1(x) (ror32(x, 6) ^ ror32(x, 11) ^ ror32(x, 25))
#define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) #define s0(x) (ror32(x, 7) ^ ror32(x, 18) ^ (x >> 3))
#define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) #define s1(x) (ror32(x, 17) ^ ror32(x, 19) ^ (x >> 10))
#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 */ /* SHA256 round function */
#define RND(a, b, c, d, e, f, g, h, k) \ #define RND(a, b, c, d, e, f, g, h, k) \
@ -96,7 +75,7 @@ sha256_Transform(uint32_t * state, const uint8_t block[64])
int i; int i;
/* 1. Prepare message schedule W. */ /* 1. Prepare message schedule W. */
be32dec_vect(W, block, 64); be32decv(W, block, 16);
for (i = 16; i < 64; i++) for (i = 16; i < 64; i++)
W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16]; W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16];
@ -104,16 +83,16 @@ sha256_Transform(uint32_t * state, const uint8_t block[64])
memcpy(S, state, 32); memcpy(S, state, 32);
/* 3. Mix. */ /* 3. Mix. */
RNDr(S, W, 0, 0x428a2f98); RNDr(S, W, 0, 0x428a2f98);
RNDr(S, W, 1, 0x71374491); RNDr(S, W, 1, 0x71374491);
RNDr(S, W, 2, 0xb5c0fbcf); RNDr(S, W, 2, 0xb5c0fbcf);
RNDr(S, W, 3, 0xe9b5dba5); RNDr(S, W, 3, 0xe9b5dba5);
RNDr(S, W, 4, 0x3956c25b); RNDr(S, W, 4, 0x3956c25b);
RNDr(S, W, 5, 0x59f111f1); RNDr(S, W, 5, 0x59f111f1);
RNDr(S, W, 6, 0x923f82a4); RNDr(S, W, 6, 0x923f82a4);
RNDr(S, W, 7, 0xab1c5ed5); RNDr(S, W, 7, 0xab1c5ed5);
RNDr(S, W, 8, 0xd807aa98); RNDr(S, W, 8, 0xd807aa98);
RNDr(S, W, 9, 0x12835b01); RNDr(S, W, 9, 0x12835b01);
RNDr(S, W, 10, 0x243185be); RNDr(S, W, 10, 0x243185be);
RNDr(S, W, 11, 0x550c7dc3); RNDr(S, W, 11, 0x550c7dc3);
RNDr(S, W, 12, 0x72be5d74); RNDr(S, W, 12, 0x72be5d74);
@ -172,18 +151,17 @@ sha256_Transform(uint32_t * state, const uint8_t block[64])
/* 4. Mix local working variables into global state. */ /* 4. Mix local working variables into global state. */
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
state[i] += S[i]; state[i] += S[i];
/* Clean the stack. */
memset(W, 0, 256);
memset(S, 0, 32);
t0 = t1 = 0;
} }
static uint8_t PAD[64] = { static uint8_t PAD[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
}; };
/* Add padding and terminating bit-count. */ /* Add padding and terminating bit-count. */
@ -286,10 +264,10 @@ sha256_final(sha256_ctx * ctx, uint8_t *digest)
sha256_pad(ctx); sha256_pad(ctx);
/* Write the hash. */ /* Write the hash. */
be32enc_vect(digest, ctx->state, SHA256_DIGEST_LEN); be32encv(digest, ctx->state, SHA256_DIGEST_LEN / 4);
/* Clear the context state. */ /* Clear the context state. */
memset(ctx, 0, sizeof(*ctx)); memset_s(ctx, 0, sizeof *ctx, sizeof *ctx);
} }
/** /**
@ -297,7 +275,7 @@ sha256_final(sha256_ctx * ctx, uint8_t *digest)
* Compute the SHA256 hash of ${len} bytes from $in} and write it to ${digest}. * Compute the SHA256 hash of ${len} bytes from $in} and write it to ${digest}.
*/ */
void void
sha256_complete(const void * in, size_t len, uint8_t *digest) sha256_complete(const void *in, size_t len, uint8_t *digest)
{ {
sha256_ctx ctx; sha256_ctx ctx;
@ -306,65 +284,6 @@ sha256_complete(const void * in, size_t len, uint8_t *digest)
sha256_final(&ctx, digest); sha256_final(&ctx, digest);
} }
#if 0
/**
* 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));
}
#endif
digest_algorithm sha256_digest = { digest_algorithm sha256_digest = {
.name = "sha256", .name = "sha256",
.contextlen = sizeof(sha256_ctx), .contextlen = sizeof(sha256_ctx),

View file

@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2006-2007 Christophe Devine * Copyright (c) 2006-2007 Christophe Devine
* Copyright (c) 2017 Dag-Erling Smørgrav
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -26,282 +27,263 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
/*
* 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 "cryb/impl.h"
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <cryb/bitwise.h>
#include <cryb/endian.h>
#include <cryb/memset_s.h>
#include <cryb/sha384.h> #include <cryb/sha384.h>
/* static const uint64_t sha384_h[8] = {
* 64-bit integer manipulation macros (big endian) 0xCBBB9D5DC1059ED8ULL, 0x629A292A367CD507ULL,
*/ 0x9159015A3070DD17ULL, 0x152FECD8F70E5939ULL,
#ifndef GET_UINT64_BE 0x67332667FFC00B31ULL, 0x8EB44A8768581511ULL,
#define GET_UINT64_BE(n,b,i) \ 0xDB0C2E0D64F98FA7ULL, 0x47B5481DBEFA4FA4ULL,
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) ] = (uint8_t) ( (n) >> 56 ); \
(b)[(i) + 1] = (uint8_t) ( (n) >> 48 ); \
(b)[(i) + 2] = (uint8_t) ( (n) >> 40 ); \
(b)[(i) + 3] = (uint8_t) ( (n) >> 32 ); \
(b)[(i) + 4] = (uint8_t) ( (n) >> 24 ); \
(b)[(i) + 5] = (uint8_t) ( (n) >> 16 ); \
(b)[(i) + 6] = (uint8_t) ( (n) >> 8 ); \
(b)[(i) + 7] = (uint8_t) ( (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)
}; };
/* static const uint64_t sha384_k[80] = {
* SHA-384 context setup 0x428A2F98D728AE22ULL, 0x7137449123EF65CDULL,
*/ 0xB5C0FBCFEC4D3B2FULL, 0xE9B5DBA58189DBBCULL,
void sha384_init( sha384_ctx *ctx ) 0x3956C25BF348B538ULL, 0x59F111F1B605D019ULL,
{ 0x923F82A4AF194F9BULL, 0xAB1C5ED5DA6D8118ULL,
ctx->total[0] = 0; 0xD807AA98A3030242ULL, 0x12835B0145706FBEULL,
ctx->total[1] = 0; 0x243185BE4EE4B28CULL, 0x550C7DC3D5FFB4E2ULL,
0x72BE5D74F27B896FULL, 0x80DEB1FE3B1696B1ULL,
ctx->state[0] = UL64(0xCBBB9D5DC1059ED8); 0x9BDC06A725C71235ULL, 0xC19BF174CF692694ULL,
ctx->state[1] = UL64(0x629A292A367CD507); 0xE49B69C19EF14AD2ULL, 0xEFBE4786384F25E3ULL,
ctx->state[2] = UL64(0x9159015A3070DD17); 0x0FC19DC68B8CD5B5ULL, 0x240CA1CC77AC9C65ULL,
ctx->state[3] = UL64(0x152FECD8F70E5939); 0x2DE92C6F592B0275ULL, 0x4A7484AA6EA6E483ULL,
ctx->state[4] = UL64(0x67332667FFC00B31); 0x5CB0A9DCBD41FBD4ULL, 0x76F988DA831153B5ULL,
ctx->state[5] = UL64(0x8EB44A8768581511); 0x983E5152EE66DFABULL, 0xA831C66D2DB43210ULL,
ctx->state[6] = UL64(0xDB0C2E0D64F98FA7); 0xB00327C898FB213FULL, 0xBF597FC7BEEF0EE4ULL,
ctx->state[7] = UL64(0x47B5481DBEFA4FA4); 0xC6E00BF33DA88FC2ULL, 0xD5A79147930AA725ULL,
} 0x06CA6351E003826FULL, 0x142929670A0E6E70ULL,
0x27B70A8546D22FFCULL, 0x2E1B21385C26C926ULL,
static void sha384_process( sha384_ctx *ctx, const uint8_t *data ) 0x4D2C6DFC5AC42AEDULL, 0x53380D139D95B3DFULL,
{ 0x650A73548BAF63DEULL, 0x766A0ABB3C77B2A8ULL,
int i; 0x81C2C92E47EDAEE6ULL, 0x92722C851482353BULL,
uint64_t temp1, temp2, W[80]; 0xA2BFE8A14CF10364ULL, 0xA81A664BBC423001ULL,
uint64_t A, B, C, D, E, F, G, H; 0xC24B8B70D0F89791ULL, 0xC76C51A30654BE30ULL,
0xD192E819D6EF5218ULL, 0xD69906245565A910ULL,
#define SHR(x,n) (x >> n) 0xF40E35855771202AULL, 0x106AA07032BBD1B8ULL,
#define ROTR(x,n) (SHR(x,n) | (x << (64 - n))) 0x19A4C116B8D2D0C8ULL, 0x1E376C085141AB53ULL,
0x2748774CDF8EEB99ULL, 0x34B0BCB5E19B48A8ULL,
#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7)) 0x391C0CB3C5C95A63ULL, 0x4ED8AA4AE3418ACBULL,
#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6)) 0x5B9CCA4F7763E373ULL, 0x682E6FF3D6B2B8A3ULL,
0x748F82EE5DEFB2FCULL, 0x78A5636F43172F60ULL,
#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39)) 0x84C87814A1F0AB72ULL, 0x8CC702081A6439ECULL,
#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41)) 0x90BEFFFA23631E28ULL, 0xA4506CEBDE82BDE9ULL,
0xBEF9A3F7B2C67915ULL, 0xC67178F2E372532BULL,
#define F0(x,y,z) ((x & y) | (z & (x | y))) 0xCA273ECEEA26619CULL, 0xD186B8C721C0C207ULL,
#define F1(x,y,z) (z ^ (x & (y ^ z))) 0xEADA7DD6CDE0EB1EULL, 0xF57D4F7FEE6ED178ULL,
0x06F067AA72176FBAULL, 0x0A637DC5A2C898A6ULL,
#define P(a,b,c,d,e,f,g,h,x,K) \ 0x113F9804BEF90DAEULL, 0x1B710B35131C471BULL,
{ \ 0x28DB77F523047D84ULL, 0x32CAAB7B40C72493ULL,
temp1 = h + S3(e) + F1(e,f,g) + K + x; \ 0x3C9EBE0A15C9BEBCULL, 0x431D67C49C100D4CULL,
temp2 = S2(a) + F0(a,b,c); \ 0x4CC5D4BECB3E42B6ULL, 0x597F299CFC657E2AULL,
d += temp1; h = temp1 + temp2; \ 0x5FCB6FAB3AD6FAECULL, 0x6C44198C4A475817ULL,
}
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( (ctx->buffer + left), 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( (ctx->buffer + left), input, ilen );
}
}
static const uint8_t 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
}; };
/* void
* SHA-384 final digest sha384_init(sha384_ctx *ctx)
*/
void sha384_final( sha384_ctx *ctx, uint8_t *output )
{ {
int last, padn;
uint64_t high, low;
uint8_t msglen[16];
high = ( ctx->total[0] >> 61 ) memset(ctx, 0, sizeof *ctx);
| ( ctx->total[1] << 3 ); memcpy(ctx->h, sha384_h, sizeof ctx->h);
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, (const uint8_t *) 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 );
} }
/* #define S0(x) (ror64(x, 1) ^ ror64(x, 8) ^ (x >> 7))
* output = SHA-384( input buffer ) #define S1(x) (ror64(x, 19) ^ ror64(x, 61) ^ (x >> 6))
*/
void sha384_complete( const void *input, int ilen, uint8_t *output ) #define S2(x) (ror64(x, 28) ^ ror64(x, 34) ^ ror64(x, 39))
#define S3(x) (ror64(x, 14) ^ ror64(x, 18) ^ ror64(x, 41))
#define F0(x, y, z) ((x & y) | (z & (x | y)))
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define P(i, a, b, c, d, e, f, g, h) do { \
uint64_t t0, t1; \
t0 = h + S3(e) + F1(e, f, g) + sha384_k[i] + w[i]; \
t1 = S2(a) + F0(a, b, c); \
d += t0; h = t0 + t1; \
} while (0)
static void
sha384_compute(sha384_ctx *ctx, const uint8_t *data)
{ {
sha384_ctx ctx; uint64_t w[80], A, B, C, D, E, F, G, H;
unsigned int i;
sha384_init( &ctx ); be64decv(w, data, 16);
sha384_update( &ctx, input, ilen ); for (i = 16; i < 80; i++)
sha384_final( &ctx, output ); w[i] = S1(w[i - 2]) + w[i - 7] + S0(w[i - 15]) + w[i - 16];
A = ctx->h[0];
B = ctx->h[1];
C = ctx->h[2];
D = ctx->h[3];
E = ctx->h[4];
F = ctx->h[5];
G = ctx->h[6];
H = ctx->h[7];
memset( &ctx, 0, sizeof( sha384_ctx ) ); P( 0, A, B, C, D, E, F, G, H);
P( 1, H, A, B, C, D, E, F, G);
P( 2, G, H, A, B, C, D, E, F);
P( 3, F, G, H, A, B, C, D, E);
P( 4, E, F, G, H, A, B, C, D);
P( 5, D, E, F, G, H, A, B, C);
P( 6, C, D, E, F, G, H, A, B);
P( 7, B, C, D, E, F, G, H, A);
P( 8, A, B, C, D, E, F, G, H);
P( 9, H, A, B, C, D, E, F, G);
P(10, G, H, A, B, C, D, E, F);
P(11, F, G, H, A, B, C, D, E);
P(12, E, F, G, H, A, B, C, D);
P(13, D, E, F, G, H, A, B, C);
P(14, C, D, E, F, G, H, A, B);
P(15, B, C, D, E, F, G, H, A);
P(16, A, B, C, D, E, F, G, H);
P(17, H, A, B, C, D, E, F, G);
P(18, G, H, A, B, C, D, E, F);
P(19, F, G, H, A, B, C, D, E);
P(20, E, F, G, H, A, B, C, D);
P(21, D, E, F, G, H, A, B, C);
P(22, C, D, E, F, G, H, A, B);
P(23, B, C, D, E, F, G, H, A);
P(24, A, B, C, D, E, F, G, H);
P(25, H, A, B, C, D, E, F, G);
P(26, G, H, A, B, C, D, E, F);
P(27, F, G, H, A, B, C, D, E);
P(28, E, F, G, H, A, B, C, D);
P(29, D, E, F, G, H, A, B, C);
P(30, C, D, E, F, G, H, A, B);
P(31, B, C, D, E, F, G, H, A);
P(32, A, B, C, D, E, F, G, H);
P(33, H, A, B, C, D, E, F, G);
P(34, G, H, A, B, C, D, E, F);
P(35, F, G, H, A, B, C, D, E);
P(36, E, F, G, H, A, B, C, D);
P(37, D, E, F, G, H, A, B, C);
P(38, C, D, E, F, G, H, A, B);
P(39, B, C, D, E, F, G, H, A);
P(40, A, B, C, D, E, F, G, H);
P(41, H, A, B, C, D, E, F, G);
P(42, G, H, A, B, C, D, E, F);
P(43, F, G, H, A, B, C, D, E);
P(44, E, F, G, H, A, B, C, D);
P(45, D, E, F, G, H, A, B, C);
P(46, C, D, E, F, G, H, A, B);
P(47, B, C, D, E, F, G, H, A);
P(48, A, B, C, D, E, F, G, H);
P(49, H, A, B, C, D, E, F, G);
P(50, G, H, A, B, C, D, E, F);
P(51, F, G, H, A, B, C, D, E);
P(52, E, F, G, H, A, B, C, D);
P(53, D, E, F, G, H, A, B, C);
P(54, C, D, E, F, G, H, A, B);
P(55, B, C, D, E, F, G, H, A);
P(56, A, B, C, D, E, F, G, H);
P(57, H, A, B, C, D, E, F, G);
P(58, G, H, A, B, C, D, E, F);
P(59, F, G, H, A, B, C, D, E);
P(60, E, F, G, H, A, B, C, D);
P(61, D, E, F, G, H, A, B, C);
P(62, C, D, E, F, G, H, A, B);
P(63, B, C, D, E, F, G, H, A);
P(64, A, B, C, D, E, F, G, H);
P(65, H, A, B, C, D, E, F, G);
P(66, G, H, A, B, C, D, E, F);
P(67, F, G, H, A, B, C, D, E);
P(68, E, F, G, H, A, B, C, D);
P(69, D, E, F, G, H, A, B, C);
P(70, C, D, E, F, G, H, A, B);
P(71, B, C, D, E, F, G, H, A);
P(72, A, B, C, D, E, F, G, H);
P(73, H, A, B, C, D, E, F, G);
P(74, G, H, A, B, C, D, E, F);
P(75, F, G, H, A, B, C, D, E);
P(76, E, F, G, H, A, B, C, D);
P(77, D, E, F, G, H, A, B, C);
P(78, C, D, E, F, G, H, A, B);
P(79, B, C, D, E, F, G, H, A);
ctx->h[0] += A;
ctx->h[1] += B;
ctx->h[2] += C;
ctx->h[3] += D;
ctx->h[4] += E;
ctx->h[5] += F;
ctx->h[6] += G;
ctx->h[7] += H;
}
void
sha384_update(sha384_ctx *ctx, const void *buf, size_t len)
{
size_t copylen;
while (len) {
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 == sizeof ctx->block) {
sha384_compute(ctx, ctx->block);
ctx->blocklen = 0;
}
} else {
copylen = sizeof ctx->block;
sha384_compute(ctx, buf);
}
if ((ctx->bitlen[1] += copylen * 8) < copylen * 8)
ctx->bitlen[0]++;
buf += copylen;
len -= copylen;
}
}
void
sha384_final(sha384_ctx *ctx, uint8_t *digest)
{
ctx->block[ctx->blocklen++] = 0x80;
memset(ctx->block + ctx->blocklen, 0,
sizeof ctx->block - ctx->blocklen);
if (ctx->blocklen > 112) {
sha384_compute(ctx, ctx->block);
ctx->blocklen = 0;
memset(ctx->block, 0, sizeof ctx->block);
}
be64encv(ctx->block + 112, ctx->bitlen, 2);
sha384_compute(ctx, ctx->block);
be64encv(digest, ctx->h, 6);
memset_s(ctx, 0, sizeof *ctx, sizeof *ctx);
}
void
sha384_complete(const void *buf, size_t len, uint8_t *digest)
{
sha384_ctx ctx;
sha384_init(&ctx);
sha384_update(&ctx, buf, len);
sha384_final(&ctx, digest);
} }
digest_algorithm sha384_digest = { digest_algorithm sha384_digest = {

View file

@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2006-2007 Christophe Devine * Copyright (c) 2006-2007 Christophe Devine
* Copyright (c) 2017 Dag-Erling Smørgrav
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -26,285 +27,263 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
/*
* 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 "cryb/impl.h"
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <cryb/bitwise.h>
#include <cryb/endian.h>
#include <cryb/memset_s.h>
#include <cryb/sha512.h> #include <cryb/sha512.h>
/* static const uint64_t sha512_h[8] = {
* 64-bit integer manipulation macros (big endian) 0x6A09E667F3BCC908ULL, 0xBB67AE8584CAA73BULL,
*/ 0x3C6EF372FE94F82BULL, 0xA54FF53A5F1D36F1ULL,
#ifndef GET_UINT64_BE 0x510E527FADE682D1ULL, 0x9B05688C2B3E6C1FULL,
#define GET_UINT64_BE(n,b,i) \ 0x1F83D9ABFB41BD6BULL, 0x5BE0CD19137E2179ULL,
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) ] = (uint8_t) ( (n) >> 56 ); \
(b)[(i) + 1] = (uint8_t) ( (n) >> 48 ); \
(b)[(i) + 2] = (uint8_t) ( (n) >> 40 ); \
(b)[(i) + 3] = (uint8_t) ( (n) >> 32 ); \
(b)[(i) + 4] = (uint8_t) ( (n) >> 24 ); \
(b)[(i) + 5] = (uint8_t) ( (n) >> 16 ); \
(b)[(i) + 6] = (uint8_t) ( (n) >> 8 ); \
(b)[(i) + 7] = (uint8_t) ( (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)
}; };
/* static const uint64_t sha512_k[80] = {
* SHA-512 context setup 0x428A2F98D728AE22ULL, 0x7137449123EF65CDULL,
*/ 0xB5C0FBCFEC4D3B2FULL, 0xE9B5DBA58189DBBCULL,
void sha512_init( sha512_ctx *ctx ) 0x3956C25BF348B538ULL, 0x59F111F1B605D019ULL,
{ 0x923F82A4AF194F9BULL, 0xAB1C5ED5DA6D8118ULL,
ctx->total[0] = 0; 0xD807AA98A3030242ULL, 0x12835B0145706FBEULL,
ctx->total[1] = 0; 0x243185BE4EE4B28CULL, 0x550C7DC3D5FFB4E2ULL,
0x72BE5D74F27B896FULL, 0x80DEB1FE3B1696B1ULL,
ctx->state[0] = UL64(0x6A09E667F3BCC908); 0x9BDC06A725C71235ULL, 0xC19BF174CF692694ULL,
ctx->state[1] = UL64(0xBB67AE8584CAA73B); 0xE49B69C19EF14AD2ULL, 0xEFBE4786384F25E3ULL,
ctx->state[2] = UL64(0x3C6EF372FE94F82B); 0x0FC19DC68B8CD5B5ULL, 0x240CA1CC77AC9C65ULL,
ctx->state[3] = UL64(0xA54FF53A5F1D36F1); 0x2DE92C6F592B0275ULL, 0x4A7484AA6EA6E483ULL,
ctx->state[4] = UL64(0x510E527FADE682D1); 0x5CB0A9DCBD41FBD4ULL, 0x76F988DA831153B5ULL,
ctx->state[5] = UL64(0x9B05688C2B3E6C1F); 0x983E5152EE66DFABULL, 0xA831C66D2DB43210ULL,
ctx->state[6] = UL64(0x1F83D9ABFB41BD6B); 0xB00327C898FB213FULL, 0xBF597FC7BEEF0EE4ULL,
ctx->state[7] = UL64(0x5BE0CD19137E2179); 0xC6E00BF33DA88FC2ULL, 0xD5A79147930AA725ULL,
} 0x06CA6351E003826FULL, 0x142929670A0E6E70ULL,
0x27B70A8546D22FFCULL, 0x2E1B21385C26C926ULL,
static void sha512_process( sha512_ctx *ctx, const uint8_t *data ) 0x4D2C6DFC5AC42AEDULL, 0x53380D139D95B3DFULL,
{ 0x650A73548BAF63DEULL, 0x766A0ABB3C77B2A8ULL,
int i; 0x81C2C92E47EDAEE6ULL, 0x92722C851482353BULL,
uint64_t temp1, temp2, W[80]; 0xA2BFE8A14CF10364ULL, 0xA81A664BBC423001ULL,
uint64_t A, B, C, D, E, F, G, H; 0xC24B8B70D0F89791ULL, 0xC76C51A30654BE30ULL,
0xD192E819D6EF5218ULL, 0xD69906245565A910ULL,
#define SHR(x,n) (x >> n) 0xF40E35855771202AULL, 0x106AA07032BBD1B8ULL,
#define ROTR(x,n) (SHR(x,n) | (x << (64 - n))) 0x19A4C116B8D2D0C8ULL, 0x1E376C085141AB53ULL,
0x2748774CDF8EEB99ULL, 0x34B0BCB5E19B48A8ULL,
#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7)) 0x391C0CB3C5C95A63ULL, 0x4ED8AA4AE3418ACBULL,
#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6)) 0x5B9CCA4F7763E373ULL, 0x682E6FF3D6B2B8A3ULL,
0x748F82EE5DEFB2FCULL, 0x78A5636F43172F60ULL,
#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39)) 0x84C87814A1F0AB72ULL, 0x8CC702081A6439ECULL,
#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41)) 0x90BEFFFA23631E28ULL, 0xA4506CEBDE82BDE9ULL,
0xBEF9A3F7B2C67915ULL, 0xC67178F2E372532BULL,
#define F0(x,y,z) ((x & y) | (z & (x | y))) 0xCA273ECEEA26619CULL, 0xD186B8C721C0C207ULL,
#define F1(x,y,z) (z ^ (x & (y ^ z))) 0xEADA7DD6CDE0EB1EULL, 0xF57D4F7FEE6ED178ULL,
0x06F067AA72176FBAULL, 0x0A637DC5A2C898A6ULL,
#define P(a,b,c,d,e,f,g,h,x,K) \ 0x113F9804BEF90DAEULL, 0x1B710B35131C471BULL,
{ \ 0x28DB77F523047D84ULL, 0x32CAAB7B40C72493ULL,
temp1 = h + S3(e) + F1(e,f,g) + K + x; \ 0x3C9EBE0A15C9BEBCULL, 0x431D67C49C100D4CULL,
temp2 = S2(a) + F0(a,b,c); \ 0x4CC5D4BECB3E42B6ULL, 0x597F299CFC657E2AULL,
d += temp1; h = temp1 + temp2; \ 0x5FCB6FAB3AD6FAECULL, 0x6C44198C4A475817ULL,
}
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( (ctx->buffer + left), 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( (ctx->buffer + left), input, ilen );
}
}
static const uint8_t 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
}; };
/* void
* SHA-512 final digest sha512_init(sha512_ctx *ctx)
*/
void sha512_final( sha512_ctx *ctx, uint8_t *output )
{ {
int last, padn;
uint64_t high, low;
uint8_t msglen[16];
high = ( ctx->total[0] >> 61 ) memset(ctx, 0, sizeof *ctx);
| ( ctx->total[1] << 3 ); memcpy(ctx->h, sha512_h, sizeof ctx->h);
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, (const uint8_t *) 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 );
PUT_UINT64_BE( ctx->state[6], output, 48 );
PUT_UINT64_BE( ctx->state[7], output, 56 );
} }
/* #define S0(x) (ror64(x, 1) ^ ror64(x, 8) ^ (x >> 7))
* output = SHA-512( input buffer ) #define S1(x) (ror64(x, 19) ^ ror64(x, 61) ^ (x >> 6))
*/
void sha512_complete( const void *input, int ilen, uint8_t *output ) #define S2(x) (ror64(x, 28) ^ ror64(x, 34) ^ ror64(x, 39))
#define S3(x) (ror64(x, 14) ^ ror64(x, 18) ^ ror64(x, 41))
#define F0(x, y, z) ((x & y) | (z & (x | y)))
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define P(i, a, b, c, d, e, f, g, h) do { \
uint64_t t0, t1; \
t0 = h + S3(e) + F1(e, f, g) + sha512_k[i] + w[i]; \
t1 = S2(a) + F0(a, b, c); \
d += t0; h = t0 + t1; \
} while (0)
static void
sha512_compute(sha512_ctx *ctx, const uint8_t *data)
{ {
sha512_ctx ctx; uint64_t w[80], A, B, C, D, E, F, G, H;
unsigned int i;
sha512_init( &ctx ); be64decv(w, data, 16);
sha512_update( &ctx, input, ilen ); for (i = 16; i < 80; i++)
sha512_final( &ctx, output ); w[i] = S1(w[i - 2]) + w[i - 7] + S0(w[i - 15]) + w[i - 16];
A = ctx->h[0];
B = ctx->h[1];
C = ctx->h[2];
D = ctx->h[3];
E = ctx->h[4];
F = ctx->h[5];
G = ctx->h[6];
H = ctx->h[7];
memset( &ctx, 0, sizeof( sha512_ctx ) ); P( 0, A, B, C, D, E, F, G, H);
P( 1, H, A, B, C, D, E, F, G);
P( 2, G, H, A, B, C, D, E, F);
P( 3, F, G, H, A, B, C, D, E);
P( 4, E, F, G, H, A, B, C, D);
P( 5, D, E, F, G, H, A, B, C);
P( 6, C, D, E, F, G, H, A, B);
P( 7, B, C, D, E, F, G, H, A);
P( 8, A, B, C, D, E, F, G, H);
P( 9, H, A, B, C, D, E, F, G);
P(10, G, H, A, B, C, D, E, F);
P(11, F, G, H, A, B, C, D, E);
P(12, E, F, G, H, A, B, C, D);
P(13, D, E, F, G, H, A, B, C);
P(14, C, D, E, F, G, H, A, B);
P(15, B, C, D, E, F, G, H, A);
P(16, A, B, C, D, E, F, G, H);
P(17, H, A, B, C, D, E, F, G);
P(18, G, H, A, B, C, D, E, F);
P(19, F, G, H, A, B, C, D, E);
P(20, E, F, G, H, A, B, C, D);
P(21, D, E, F, G, H, A, B, C);
P(22, C, D, E, F, G, H, A, B);
P(23, B, C, D, E, F, G, H, A);
P(24, A, B, C, D, E, F, G, H);
P(25, H, A, B, C, D, E, F, G);
P(26, G, H, A, B, C, D, E, F);
P(27, F, G, H, A, B, C, D, E);
P(28, E, F, G, H, A, B, C, D);
P(29, D, E, F, G, H, A, B, C);
P(30, C, D, E, F, G, H, A, B);
P(31, B, C, D, E, F, G, H, A);
P(32, A, B, C, D, E, F, G, H);
P(33, H, A, B, C, D, E, F, G);
P(34, G, H, A, B, C, D, E, F);
P(35, F, G, H, A, B, C, D, E);
P(36, E, F, G, H, A, B, C, D);
P(37, D, E, F, G, H, A, B, C);
P(38, C, D, E, F, G, H, A, B);
P(39, B, C, D, E, F, G, H, A);
P(40, A, B, C, D, E, F, G, H);
P(41, H, A, B, C, D, E, F, G);
P(42, G, H, A, B, C, D, E, F);
P(43, F, G, H, A, B, C, D, E);
P(44, E, F, G, H, A, B, C, D);
P(45, D, E, F, G, H, A, B, C);
P(46, C, D, E, F, G, H, A, B);
P(47, B, C, D, E, F, G, H, A);
P(48, A, B, C, D, E, F, G, H);
P(49, H, A, B, C, D, E, F, G);
P(50, G, H, A, B, C, D, E, F);
P(51, F, G, H, A, B, C, D, E);
P(52, E, F, G, H, A, B, C, D);
P(53, D, E, F, G, H, A, B, C);
P(54, C, D, E, F, G, H, A, B);
P(55, B, C, D, E, F, G, H, A);
P(56, A, B, C, D, E, F, G, H);
P(57, H, A, B, C, D, E, F, G);
P(58, G, H, A, B, C, D, E, F);
P(59, F, G, H, A, B, C, D, E);
P(60, E, F, G, H, A, B, C, D);
P(61, D, E, F, G, H, A, B, C);
P(62, C, D, E, F, G, H, A, B);
P(63, B, C, D, E, F, G, H, A);
P(64, A, B, C, D, E, F, G, H);
P(65, H, A, B, C, D, E, F, G);
P(66, G, H, A, B, C, D, E, F);
P(67, F, G, H, A, B, C, D, E);
P(68, E, F, G, H, A, B, C, D);
P(69, D, E, F, G, H, A, B, C);
P(70, C, D, E, F, G, H, A, B);
P(71, B, C, D, E, F, G, H, A);
P(72, A, B, C, D, E, F, G, H);
P(73, H, A, B, C, D, E, F, G);
P(74, G, H, A, B, C, D, E, F);
P(75, F, G, H, A, B, C, D, E);
P(76, E, F, G, H, A, B, C, D);
P(77, D, E, F, G, H, A, B, C);
P(78, C, D, E, F, G, H, A, B);
P(79, B, C, D, E, F, G, H, A);
ctx->h[0] += A;
ctx->h[1] += B;
ctx->h[2] += C;
ctx->h[3] += D;
ctx->h[4] += E;
ctx->h[5] += F;
ctx->h[6] += G;
ctx->h[7] += H;
}
void
sha512_update(sha512_ctx *ctx, const void *buf, size_t len)
{
size_t copylen;
while (len) {
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 == sizeof ctx->block) {
sha512_compute(ctx, ctx->block);
ctx->blocklen = 0;
}
} else {
copylen = sizeof ctx->block;
sha512_compute(ctx, buf);
}
if ((ctx->bitlen[1] += copylen * 8) < copylen * 8)
ctx->bitlen[0]++;
buf += copylen;
len -= copylen;
}
}
void
sha512_final(sha512_ctx *ctx, uint8_t *digest)
{
ctx->block[ctx->blocklen++] = 0x80;
memset(ctx->block + ctx->blocklen, 0,
sizeof ctx->block - ctx->blocklen);
if (ctx->blocklen > 112) {
sha512_compute(ctx, ctx->block);
ctx->blocklen = 0;
memset(ctx->block, 0, sizeof ctx->block);
}
be64encv(ctx->block + 112, ctx->bitlen, 2);
sha512_compute(ctx, ctx->block);
be64encv(digest, ctx->h, 8);
memset_s(ctx, 0, sizeof *ctx, sizeof *ctx);
}
void
sha512_complete(const void *buf, size_t len, uint8_t *digest)
{
sha512_ctx ctx;
sha512_init(&ctx);
sha512_update(&ctx, buf, len);
sha512_final(&ctx, digest);
} }
digest_algorithm sha512_digest = { digest_algorithm sha512_digest = {

View file

@ -229,22 +229,19 @@ t_sha384_carry(char **desc CRYB_UNUSED, void *arg CRYB_UNUSED)
sha384_ctx ctx; sha384_ctx ctx;
uint8_t digest[SHA384_DIGEST_LEN]; uint8_t digest[SHA384_DIGEST_LEN];
static uint8_t expect[SHA384_DIGEST_LEN] = { static uint8_t expect[SHA384_DIGEST_LEN] = {
0x04, 0xa8, 0xab, 0x2a, 0x7d, 0xe6, 0x68, 0x22, 0x04, 0x69, 0xc2, 0x19, 0xcd, 0x88, 0x40, 0xf9,
0xcd, 0x45, 0xfd, 0xc5, 0x41, 0x62, 0x32, 0xca, 0xbb, 0xb6, 0xd8, 0x68, 0xab, 0x24, 0xf1, 0x5e,
0x6c, 0x59, 0x92, 0x41, 0x77, 0x99, 0xca, 0xa7, 0x35, 0x79, 0xa9, 0xfc, 0xf3, 0x21, 0xc2, 0x27,
0xe2, 0xf0, 0x28, 0x77, 0x2b, 0x33, 0xbe, 0xa0, 0x79, 0x1f, 0x0a, 0x73, 0x4a, 0x50, 0x73, 0x24,
0xbe, 0xee, 0x4d, 0xd1, 0x9e, 0x18, 0xc4, 0x5f, 0xfe, 0xcd, 0x3a, 0xca, 0x22, 0x5d, 0x22, 0xe7,
0x47, 0x91, 0xb3, 0xd1, 0x9c, 0x3a, 0x81, 0xfb, 0x7e, 0x1c, 0x75, 0xcb, 0x72, 0xee, 0x3a, 0xf8,
}; };
sha384_init(&ctx); sha384_init(&ctx);
#if WITH_OPENSSL #if WITH_OPENSSL
/* openssl counts bits */ ctx.Nl = 0xfffffffffffffc00LLU;
ctx.Nl = 0xffffffffffffff80LLU << 3LLU;
ctx.Nh = 0xffffffffffffff80LLU >> 61LLU;
#else #else
/* cryb counts bytes and multiplies at the end */ ctx.bitlen[1] = 0xfffffffffffffc00LLU;
ctx.total[0] = 0xffffffffffffff80LLU;
#endif #endif
sha384_update(&ctx, t_seq8, 256); sha384_update(&ctx, t_seq8, 256);
sha384_final(&ctx, digest); sha384_final(&ctx, digest);

View file

@ -239,24 +239,21 @@ t_sha512_carry(char **desc CRYB_UNUSED, void *arg CRYB_UNUSED)
sha512_ctx ctx; sha512_ctx ctx;
uint8_t digest[SHA512_DIGEST_LEN]; uint8_t digest[SHA512_DIGEST_LEN];
static uint8_t expect[SHA512_DIGEST_LEN] = { static uint8_t expect[SHA512_DIGEST_LEN] = {
0xbd, 0x25, 0x6d, 0xa8, 0xbf, 0xe0, 0x6c, 0xf0, 0x00, 0x79, 0xb9, 0x71, 0xd3, 0x86, 0x0b, 0x53,
0xc1, 0x8c, 0xe9, 0x58, 0xb8, 0xce, 0x43, 0xc7, 0x64, 0xc7, 0x37, 0x63, 0x97, 0x8f, 0x35, 0x14,
0x9a, 0x3d, 0xec, 0x10, 0x58, 0x55, 0x00, 0x7f, 0xed, 0x53, 0x20, 0x3d, 0xae, 0x03, 0xa0, 0x37,
0xe7, 0x75, 0x48, 0x66, 0xb2, 0x18, 0xc3, 0x98, 0x70, 0xbe, 0xce, 0x70, 0x87, 0x20, 0x21, 0x16,
0x91, 0x11, 0x75, 0x88, 0x53, 0x3e, 0xb3, 0x4b, 0x43, 0x8d, 0x3f, 0xe2, 0xbc, 0x02, 0xf0, 0x8c,
0x83, 0x93, 0xca, 0x18, 0x8a, 0xbe, 0x32, 0x7d, 0xc9, 0x98, 0x4c, 0x4d, 0xf3, 0x6f, 0x0b, 0xbb,
0x4a, 0x54, 0x16, 0xbb, 0xdf, 0x9e, 0x9c, 0x3a, 0x55, 0x94, 0x70, 0x95, 0xf1, 0x9f, 0xaf, 0xaf,
0xd7, 0x22, 0xc8, 0x0d, 0x71, 0x0f, 0x76, 0xc0, 0xd6, 0xbb, 0x3a, 0xbb, 0x4d, 0x6a, 0xf0, 0xc0,
}; };
sha512_init(&ctx); sha512_init(&ctx);
#if WITH_OPENSSL #if WITH_OPENSSL
/* openssl counts bits */ ctx.Nl = 0xfffffffffffffc00LLU;
ctx.Nl = 0xffffffffffffff80LLU << 3LLU;
ctx.Nh = 0xffffffffffffff80LLU >> 61LLU;
#else #else
/* cryb counts bytes and multiplies at the end */ ctx.bitlen[1] = 0xfffffffffffffc00LLU;
ctx.total[0] = 0xffffffffffffff80LLU;
#endif #endif
sha512_update(&ctx, t_seq8, 256); sha512_update(&ctx, t_seq8, 256);
sha512_final(&ctx, digest); sha512_final(&ctx, digest);