mirror of https://github.com/aria2/aria2
Fix big endianess support in InternalMessageDigest and PBKDF2
- Replace sha1/md5 implementation by ones from https://github.com/nmaier/crypto - Add endianess functionality fro https://github.com/nmaier/crypto Closes GH-239pull/239/merge
parent
60032bf0ab
commit
8587669995
|
@ -35,81 +35,71 @@
|
|||
|
||||
#include "MessageDigestImpl.h"
|
||||
|
||||
#include "md5.h"
|
||||
#include "sha1.h"
|
||||
#include "crypto_hash.h"
|
||||
|
||||
namespace aria2 {
|
||||
namespace {
|
||||
using namespace aria2;
|
||||
using namespace crypto;
|
||||
|
||||
template<size_t dlen,
|
||||
typename ctx_t,
|
||||
int (*init_fn)(ctx_t**),
|
||||
void (*update_fn)(ctx_t*, const void*, size_t),
|
||||
void (*final_fn)(ctx_t*, uint8_t*),
|
||||
void (*free_fn)(ctx_t**)>
|
||||
class MessageDigestBase : public MessageDigestImpl {
|
||||
template<hash::Algorithms algo>
|
||||
class MessageDigestBase : public MessageDigestImpl
|
||||
{
|
||||
public:
|
||||
MessageDigestBase() : ctx_(nullptr) { reset(); }
|
||||
virtual ~MessageDigestBase()
|
||||
MessageDigestBase() : ctx_{hash::create(algo)} {}
|
||||
virtual ~MessageDigestBase() {}
|
||||
|
||||
static size_t length()
|
||||
{
|
||||
free_fn(&ctx_);
|
||||
auto ctx = hash::create(algo);
|
||||
return ctx->length();
|
||||
}
|
||||
|
||||
static size_t length()
|
||||
{
|
||||
return dlen;
|
||||
}
|
||||
virtual size_t getDigestLength() const CXX11_OVERRIDE
|
||||
{
|
||||
return dlen;
|
||||
return ctx_->length();
|
||||
}
|
||||
|
||||
virtual void reset() CXX11_OVERRIDE
|
||||
{
|
||||
free_fn(&ctx_);
|
||||
init_fn(&ctx_);
|
||||
ctx_->reset();
|
||||
}
|
||||
virtual void update(const void* data, size_t length) CXX11_OVERRIDE
|
||||
|
||||
virtual void update(const void *data, size_t length) CXX11_OVERRIDE
|
||||
{
|
||||
auto bytes = reinterpret_cast<const char*>(data);
|
||||
while (length) {
|
||||
size_t l = std::min(length, (size_t)std::numeric_limits<uint32_t>::max());
|
||||
update_fn(ctx_, bytes, l);
|
||||
length -= l;
|
||||
bytes += l;
|
||||
}
|
||||
ctx_->update(data, length);
|
||||
}
|
||||
virtual void digest(unsigned char* md) CXX11_OVERRIDE
|
||||
|
||||
virtual void digest(unsigned char *md) CXX11_OVERRIDE
|
||||
{
|
||||
final_fn(ctx_, md);
|
||||
auto rv = ctx_->finalize();
|
||||
memcpy(md, rv.data(), rv.length());
|
||||
}
|
||||
|
||||
private:
|
||||
ctx_t* ctx_;
|
||||
std::unique_ptr<hash::Algorithm> ctx_;
|
||||
};
|
||||
|
||||
typedef MessageDigestBase<MD5_LENGTH,
|
||||
struct MD5_CTX,
|
||||
MD5_Init,
|
||||
MD5_Update,
|
||||
MD5_Final,
|
||||
MD5_Free>
|
||||
MessageDigestMD5;
|
||||
typedef MessageDigestBase<SHA1_LENGTH,
|
||||
SHA1_CTX,
|
||||
SHA1_Init,
|
||||
SHA1_Update,
|
||||
SHA1_Final,
|
||||
SHA1_Free>
|
||||
MessageDigestSHA1;
|
||||
typedef MessageDigestBase<hash::algoMD5> MessageDigestMD5;
|
||||
typedef MessageDigestBase<hash::algoSHA1> MessageDigestSHA1;
|
||||
typedef MessageDigestBase<hash::algoSHA224> MessageDigestSHA224;
|
||||
typedef MessageDigestBase<hash::algoSHA256> MessageDigestSHA256;
|
||||
typedef MessageDigestBase<hash::algoSHA384> MessageDigestSHA384;
|
||||
typedef MessageDigestBase<hash::algoSHA512> MessageDigestSHA512;
|
||||
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<MessageDigestImpl> MessageDigestImpl::sha1()
|
||||
{
|
||||
namespace aria2 {
|
||||
|
||||
std::unique_ptr<MessageDigestImpl> MessageDigestImpl::sha1() {
|
||||
return make_unique<MessageDigestSHA1>();
|
||||
}
|
||||
|
||||
MessageDigestImpl::hashes_t MessageDigestImpl::hashes = {
|
||||
{ "sha-1", make_hi<MessageDigestSHA1>() },
|
||||
{ "sha-224", make_hi<MessageDigestSHA224>() },
|
||||
{ "sha-256", make_hi<MessageDigestSHA256>() },
|
||||
{ "sha-384", make_hi<MessageDigestSHA384>() },
|
||||
{ "sha-512", make_hi<MessageDigestSHA512>() },
|
||||
{ "md5", make_hi<MessageDigestMD5>() },
|
||||
};
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ SRCS = \
|
|||
CookieStorage.cc CookieStorage.h\
|
||||
cookie_helper.cc cookie_helper.h\
|
||||
CreateRequestCommand.cc CreateRequestCommand.h\
|
||||
crypto_endian.h\
|
||||
CUIDCounter.cc CUIDCounter.h\
|
||||
DefaultAuthResolver.cc DefaultAuthResolver.h\
|
||||
DefaultBtProgressInfoFile.cc DefaultBtProgressInfoFile.h\
|
||||
|
@ -370,8 +371,7 @@ endif
|
|||
if USE_INTERNAL_MD
|
||||
SRCS += \
|
||||
InternalMessageDigestImpl.cc\
|
||||
md5.c md5.h\
|
||||
sha1.c sha1.h
|
||||
crypto_hash.cc crypto_hash.h
|
||||
endif # USE_WINDOWS_MD
|
||||
|
||||
if HAVE_LIBGNUTLS
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
// Written in 2014 by Nils Maier
|
||||
|
||||
#ifndef CRYPTO_ENDIAN_H
|
||||
#define CRYPTO_ENDIAN_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
namespace crypto {
|
||||
|
||||
#if defined(__GNUG__)
|
||||
#define forceinline __attribute__((always_inline)) inline
|
||||
#elif defined(_MSC_VER)
|
||||
#define forceinline __forceinline
|
||||
#else // ! _MSC_VER
|
||||
#define forceinline inline
|
||||
#endif // ! _MSC_VER
|
||||
|
||||
/* In order for this implementation to work your system (or you yourself) must
|
||||
* define after including <sys/param.h>
|
||||
* - LITTLE_ENDIAN
|
||||
* - BIG_ENDIAN
|
||||
* - BYTE_ORDER
|
||||
* - where BYTE_ORDER == LITTLE_ENDIAN or BYTE_ORDER == BIG_ENDIAN
|
||||
* Failing to conform will render this implementation utterly incorrect.
|
||||
*/
|
||||
#if defined(_WIN32) || defined(__INTEL_COMPILER) || defined (_MSC_VER)
|
||||
// Itanium is dead!
|
||||
#define LITTLE_ENDIAN 1234
|
||||
#define BIG_ENDIAN 4321
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
#else // ! defined(_WIN32) || defined(__INTEL_COMPILER) || defined (_MSC_VER)
|
||||
#ifdef HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif // HAVE_SYS_PARAM_H
|
||||
#endif // ! defined(_WIN32) || defined(__INTEL_COMPILER) || defined (_MSC_VER)
|
||||
|
||||
#if !defined(LITTLE_ENDIAN) || !defined(BIG_ENDIAN) || !defined(BYTE_ORDER) || (LITTLE_ENDIAN != BYTE_ORDER && BIG_ENDIAN != BYTE_ORDER)
|
||||
#error Unsupported byte order/endianess
|
||||
#endif
|
||||
|
||||
// Lets spend some quality time mucking around with byte swap and endian-ness.
|
||||
// First bswap32:
|
||||
#if (defined(__i386__) || defined(__x86_64__)) && defined(__GNUG__)
|
||||
#define __crypto_bswap32(p) \
|
||||
({ \
|
||||
uint32_t t = p; \
|
||||
__asm__ __volatile__("bswap %0" : "=r"(t) : "0"(t)); \
|
||||
t; \
|
||||
})
|
||||
#elif defined(__GNUG__)
|
||||
#define __crypto_bswap32 __builtin_bswap32
|
||||
#else // defined(__GNUG__)
|
||||
forceinline uint32_t __crypto_bswap32(uint32_t n)
|
||||
{
|
||||
n = ((n << 8) & 0xff00ff00) | ((n >> 8) & 0xff00ff);
|
||||
return (n << 16) | (n >> 16);
|
||||
}
|
||||
#endif // defined(__GNUG__)
|
||||
|
||||
// Next up: bswap64
|
||||
#if defined(__x86_64__) && defined(__GNUG__)
|
||||
#define __crypto_bswap64(p) \
|
||||
({ \
|
||||
uint64_t t = p; \
|
||||
__asm__ __volatile__("bswapq %q0" : "=r"(t) : "0"(t)); \
|
||||
t; \
|
||||
})
|
||||
|
||||
#elif defined(__GNUG__)
|
||||
#define __crypto_bswap64 __builtin_bswap64
|
||||
#else // defined(__GNUG__)
|
||||
forceinline uint64_t __crypto_bswap64(uint64_t n)
|
||||
{
|
||||
n = ((n << 8) & 0xff00ff00ff00ff00) | ((n >> 8) & 0x00ff00ff00ff00ff);
|
||||
n = ((n << 16) & 0xffff0000ffff0000) | ((n >> 16) & 0x0000ffff0000ffff);
|
||||
return (n << 32) | (n >> 32);
|
||||
}
|
||||
#endif // defined(__GNUG__)
|
||||
|
||||
// Time for an implementation that makes reuse easier.
|
||||
namespace {
|
||||
template<typename T>
|
||||
inline T __crypto_bswap(T n)
|
||||
{
|
||||
static_assert(sizeof(T) != sizeof(T), "Not implemented");
|
||||
}
|
||||
|
||||
template<>
|
||||
inline uint32_t __crypto_bswap(uint32_t n)
|
||||
{
|
||||
return __crypto_bswap32(n);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline uint64_t __crypto_bswap(uint64_t n)
|
||||
{
|
||||
return __crypto_bswap64(n);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// __crypto_le and __crypto_be depending on byte order
|
||||
#if LITTLE_ENDIAN == BYTE_ORDER
|
||||
#define __crypto_be(n) __crypto_bswap(n)
|
||||
#define __crypto_le(n) (n)
|
||||
#else // LITTLE_ENDIAN == WORD_ORDER
|
||||
#define __crypto_be(n) (n)
|
||||
#define __crypto_le(n) __crypto_bswap(n)
|
||||
#endif
|
||||
|
||||
} // namespace crypto
|
||||
|
||||
#endif // CRYPTO_ENDIAN_H
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,103 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
// Written in 2014 by Nils Maier
|
||||
|
||||
#ifndef CRYPTO_HASH_H
|
||||
#define CRYPTO_HASH_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <limits>
|
||||
|
||||
namespace crypto {
|
||||
namespace hash {
|
||||
|
||||
enum Algorithms {
|
||||
algoNone = 0x0,
|
||||
algoMD5 = 0x1,
|
||||
algoSHA1 = 0x2,
|
||||
algoSHA224 = 0x3,
|
||||
algoSHA256 = 0x4,
|
||||
algoSHA384 = 0x5,
|
||||
algoSHA512 = 0x6,
|
||||
};
|
||||
|
||||
class Algorithm
|
||||
{
|
||||
public:
|
||||
Algorithm() {}
|
||||
|
||||
virtual ~Algorithm() {}
|
||||
|
||||
virtual void update(const void* data, uint64_t len) = 0;
|
||||
|
||||
inline void update(const std::string& data)
|
||||
{
|
||||
return update(data.data(), data.length());
|
||||
}
|
||||
|
||||
virtual std::string finalize() = 0;
|
||||
|
||||
virtual void reset() = 0;
|
||||
|
||||
virtual uint_fast16_t length() const = 0;
|
||||
|
||||
virtual uint_fast16_t blocksize() const = 0;
|
||||
|
||||
private:
|
||||
Algorithm(const Algorithm&) = delete;
|
||||
|
||||
Algorithm& operator=(const Algorithm&) = delete;
|
||||
};
|
||||
|
||||
const std::set<std::string>& all();
|
||||
|
||||
Algorithms lookup(const std::string& name);
|
||||
|
||||
std::unique_ptr<Algorithm> create(Algorithms algo);
|
||||
|
||||
inline std::unique_ptr<Algorithm> create(const std::string& name)
|
||||
{
|
||||
return create(lookup(name));
|
||||
}
|
||||
|
||||
inline uint_fast16_t length(Algorithms algo)
|
||||
{
|
||||
return create(algo)->length();
|
||||
}
|
||||
|
||||
inline uint_fast16_t length(const std::string& name)
|
||||
{
|
||||
return create(name)->length();
|
||||
}
|
||||
|
||||
inline std::string compute(Algorithms algo, const void* data, uint_fast64_t len)
|
||||
{
|
||||
auto ctx = create(algo);
|
||||
ctx->update(data, len);
|
||||
return ctx->finalize();
|
||||
}
|
||||
|
||||
inline std::string compute(Algorithms algo, const std::string& data)
|
||||
{
|
||||
return compute(algo, data.data(), data.length());
|
||||
}
|
||||
|
||||
inline std::string
|
||||
compute(const std::string& name, const void* data, uint_fast64_t len)
|
||||
{
|
||||
return compute(lookup(name), data, len);
|
||||
}
|
||||
|
||||
inline std::string compute(const std::string& name, const std::string& data)
|
||||
{
|
||||
return compute(lookup(name), data.data(), data.length());
|
||||
}
|
||||
|
||||
} // namespace hash
|
||||
} // namespace crypto
|
||||
|
||||
#endif // CRYPTO_HASH_H
|
311
src/md5.c
311
src/md5.c
|
@ -1,311 +0,0 @@
|
|||
/*
|
||||
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
|
||||
* MD5 Message-Digest Algorithm (RFC 1321).
|
||||
*
|
||||
* Homepage:
|
||||
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
|
||||
*
|
||||
* Author:
|
||||
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
|
||||
*
|
||||
* This software was written by Alexander Peslyak in 2001. No copyright is
|
||||
* claimed, and the software is hereby placed in the public domain.
|
||||
* In case this attempt to disclaim copyright and place the software in the
|
||||
* public domain is deemed null and void, then the software is
|
||||
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
|
||||
* general public under the following terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
*
|
||||
* (This is a heavily cut-down "BSD license".)
|
||||
*
|
||||
* This differs from Colin Plumb's older public domain implementation in that
|
||||
* no exactly 32-bit integer data type is required (any 32-bit or wider
|
||||
* unsigned integer data type will do), there's no compile-time endianness
|
||||
* configuration, and the function prototypes match OpenSSL's. No code from
|
||||
* Colin Plumb's implementation has been reused; this comment merely compares
|
||||
* the properties of the two independent implementations.
|
||||
*
|
||||
* The primary goals of this implementation are portability and ease of use.
|
||||
* It is meant to be fast, but not as fast as possible. Some known
|
||||
* optimizations are not included to reduce source code size and avoid
|
||||
* compile-time configuration.
|
||||
*/
|
||||
|
||||
#include "md5.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct MD5_CTX {
|
||||
size_t lo, hi;
|
||||
size_t a, b, c, d;
|
||||
uint8_t buffer[64];
|
||||
size_t block[16];
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* The basic MD5 functions.
|
||||
*
|
||||
* F and G are optimized compared to their RFC 1321 definitions for
|
||||
* architectures that lack an AND-NOT instruction, just like in Colin Plumb's
|
||||
* implementation.
|
||||
*/
|
||||
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
|
||||
#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
|
||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
|
||||
|
||||
/*
|
||||
* The MD5 transformation for all four rounds.
|
||||
*/
|
||||
#define STEP(f, a, b, c, d, x, t, s) \
|
||||
(a) += f((b), (c), (d)) + (x) + (t); \
|
||||
(a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
|
||||
(a) += (b);
|
||||
|
||||
/*
|
||||
* SET reads 4 input bytes in little-endian byte order and stores them
|
||||
* in a properly aligned word in host byte order.
|
||||
*
|
||||
* The check for little-endian architectures that tolerate unaligned
|
||||
* memory accesses is just an optimization. Nothing will break if it
|
||||
* doesn't work.
|
||||
*/
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
|
||||
#define SET(n) \
|
||||
(*(size_t *)&ptr[(n) * 4])
|
||||
#define GET(n) \
|
||||
SET(n)
|
||||
#else
|
||||
#define SET(n) \
|
||||
(ctx->block[(n)] = \
|
||||
(size_t)ptr[(n) * 4] | \
|
||||
((size_t)ptr[(n) * 4 + 1] << 8) | \
|
||||
((size_t)ptr[(n) * 4 + 2] << 16) | \
|
||||
((size_t)ptr[(n) * 4 + 3] << 24))
|
||||
#define GET(n) \
|
||||
(ctx->block[(n)])
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This processes one or more 64-byte data blocks, but does NOT update
|
||||
* the bit counters. There are no alignment requirements.
|
||||
*/
|
||||
static const void *body(struct MD5_CTX *ctx, const void *data, size_t size)
|
||||
{
|
||||
const uint8_t *ptr;
|
||||
size_t a, b, c, d;
|
||||
size_t saved_a, saved_b, saved_c, saved_d;
|
||||
|
||||
ptr = data;
|
||||
|
||||
a = ctx->a;
|
||||
b = ctx->b;
|
||||
c = ctx->c;
|
||||
d = ctx->d;
|
||||
|
||||
do {
|
||||
saved_a = a;
|
||||
saved_b = b;
|
||||
saved_c = c;
|
||||
saved_d = d;
|
||||
|
||||
/* Round 1 */
|
||||
STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
|
||||
STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
|
||||
STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
|
||||
STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
|
||||
STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
|
||||
STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
|
||||
STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
|
||||
STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
|
||||
STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
|
||||
STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
|
||||
STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
|
||||
STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
|
||||
STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
|
||||
STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
|
||||
STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
|
||||
STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
|
||||
|
||||
/* Round 2 */
|
||||
STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
|
||||
STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
|
||||
STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
|
||||
STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
|
||||
STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
|
||||
STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
|
||||
STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
|
||||
STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
|
||||
STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
|
||||
STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
|
||||
STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
|
||||
STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
|
||||
STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
|
||||
STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
|
||||
STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
|
||||
STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
|
||||
|
||||
/* Round 3 */
|
||||
STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
|
||||
STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
|
||||
STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
|
||||
STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
|
||||
STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
|
||||
STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
|
||||
STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
|
||||
STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
|
||||
STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
|
||||
STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
|
||||
STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
|
||||
STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
|
||||
STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
|
||||
STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
|
||||
STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
|
||||
STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
|
||||
|
||||
/* Round 4 */
|
||||
STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
|
||||
STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
|
||||
STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
|
||||
STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
|
||||
STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
|
||||
STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
|
||||
STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
|
||||
STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
|
||||
STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
|
||||
STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
|
||||
STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
|
||||
STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
|
||||
STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
|
||||
STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
|
||||
STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
|
||||
STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
|
||||
|
||||
a += saved_a;
|
||||
b += saved_b;
|
||||
c += saved_c;
|
||||
d += saved_d;
|
||||
|
||||
ptr += 64;
|
||||
} while (size -= 64);
|
||||
|
||||
ctx->a = a;
|
||||
ctx->b = b;
|
||||
ctx->c = c;
|
||||
ctx->d = d;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
int MD5_Init(struct MD5_CTX **ctx)
|
||||
{
|
||||
*ctx = malloc(sizeof(struct MD5_CTX));
|
||||
if (!*ctx) {
|
||||
return 0;
|
||||
}
|
||||
(*ctx)->a = 0x67452301;
|
||||
(*ctx)->b = 0xefcdab89;
|
||||
(*ctx)->c = 0x98badcfe;
|
||||
(*ctx)->d = 0x10325476;
|
||||
|
||||
(*ctx)->lo = 0;
|
||||
(*ctx)->hi = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void MD5_Update(struct MD5_CTX *ctx, const void *data, size_t size)
|
||||
{
|
||||
size_t saved_lo;
|
||||
size_t used, free;
|
||||
|
||||
saved_lo = ctx->lo;
|
||||
if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
|
||||
ctx->hi++;
|
||||
ctx->hi += size >> 29;
|
||||
|
||||
used = saved_lo & 0x3f;
|
||||
|
||||
if (used) {
|
||||
free = 64 - used;
|
||||
|
||||
if (size < free) {
|
||||
memcpy(&ctx->buffer[used], data, size);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&ctx->buffer[used], data, free);
|
||||
data = (unsigned char *)data + free;
|
||||
size -= free;
|
||||
body(ctx, ctx->buffer, 64);
|
||||
}
|
||||
|
||||
if (size >= 64) {
|
||||
data = body(ctx, data, size & ~(size_t)0x3f);
|
||||
size &= 0x3f;
|
||||
}
|
||||
|
||||
memcpy(ctx->buffer, data, size);
|
||||
}
|
||||
|
||||
void MD5_Final(struct MD5_CTX *ctx, unsigned char* result)
|
||||
{
|
||||
size_t used, free;
|
||||
|
||||
used = ctx->lo & 0x3f;
|
||||
|
||||
ctx->buffer[used++] = 0x80;
|
||||
|
||||
free = 64 - used;
|
||||
|
||||
if (free < 8) {
|
||||
memset(&ctx->buffer[used], 0, free);
|
||||
body(ctx, ctx->buffer, 64);
|
||||
used = 0;
|
||||
free = 64;
|
||||
}
|
||||
|
||||
memset(&ctx->buffer[used], 0, free - 8);
|
||||
|
||||
ctx->lo <<= 3;
|
||||
ctx->buffer[56] = ctx->lo;
|
||||
ctx->buffer[57] = ctx->lo >> 8;
|
||||
ctx->buffer[58] = ctx->lo >> 16;
|
||||
ctx->buffer[59] = ctx->lo >> 24;
|
||||
ctx->buffer[60] = ctx->hi;
|
||||
ctx->buffer[61] = ctx->hi >> 8;
|
||||
ctx->buffer[62] = ctx->hi >> 16;
|
||||
ctx->buffer[63] = ctx->hi >> 24;
|
||||
|
||||
body(ctx, ctx->buffer, 64);
|
||||
|
||||
result[0] = ctx->a;
|
||||
result[1] = ctx->a >> 8;
|
||||
result[2] = ctx->a >> 16;
|
||||
result[3] = ctx->a >> 24;
|
||||
result[4] = ctx->b;
|
||||
result[5] = ctx->b >> 8;
|
||||
result[6] = ctx->b >> 16;
|
||||
result[7] = ctx->b >> 24;
|
||||
result[8] = ctx->c;
|
||||
result[9] = ctx->c >> 8;
|
||||
result[10] = ctx->c >> 16;
|
||||
result[11] = ctx->c >> 24;
|
||||
result[12] = ctx->d;
|
||||
result[13] = ctx->d >> 8;
|
||||
result[14] = ctx->d >> 16;
|
||||
result[15] = ctx->d >> 24;
|
||||
}
|
||||
|
||||
void MD5_Free(struct MD5_CTX** ctx) {
|
||||
if (!ctx || !*ctx) {
|
||||
return;
|
||||
}
|
||||
free(*ctx);
|
||||
*ctx = NULL;
|
||||
}
|
47
src/md5.h
47
src/md5.h
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
|
||||
* MD5 Message-Digest Algorithm (RFC 1321).
|
||||
*
|
||||
* Homepage:
|
||||
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
|
||||
*
|
||||
* Author:
|
||||
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
|
||||
*
|
||||
* This software was written by Alexander Peslyak in 2001. No copyright is
|
||||
* claimed, and the software is hereby placed in the public domain.
|
||||
* In case this attempt to disclaim copyright and place the software in the
|
||||
* public domain is deemed null and void, then the software is
|
||||
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
|
||||
* general public under the following terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
*
|
||||
* See md5.c for more information.
|
||||
*/
|
||||
|
||||
#ifndef INTERNAL_MD5_H
|
||||
#define INTERNAL_MD5_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct MD5_CTX;
|
||||
|
||||
#define MD5_LENGTH 16
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
int MD5_Init(struct MD5_CTX **ctx);
|
||||
void MD5_Update(struct MD5_CTX *ctx, const void *data, size_t size);
|
||||
void MD5_Final(struct MD5_CTX *ctx, uint8_t *result);
|
||||
void MD5_Free(struct MD5_CTX **ctx);
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* INTERNAL_MD5_H */
|
160
src/sha1.c
160
src/sha1.c
|
@ -1,160 +0,0 @@
|
|||
/* This code is public-domain - it is based on libcrypt
|
||||
* placed in the public domain by Wei Dai and other contributors.
|
||||
*/
|
||||
|
||||
#include "sha1.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#define BLOCK_LENGTH 64
|
||||
|
||||
union _buffer {
|
||||
uint8_t b[BLOCK_LENGTH];
|
||||
uint32_t w[BLOCK_LENGTH/4];
|
||||
};
|
||||
|
||||
union _state {
|
||||
uint8_t b[SHA1_LENGTH];
|
||||
uint32_t w[SHA1_LENGTH/4];
|
||||
};
|
||||
|
||||
struct SHA1_CTX {
|
||||
union _buffer buffer;
|
||||
uint8_t bufferOffset;
|
||||
union _state state;
|
||||
uint32_t byteCount;
|
||||
uint8_t keyBuffer[BLOCK_LENGTH];
|
||||
uint8_t innerHash[SHA1_LENGTH];
|
||||
};
|
||||
|
||||
#define SHA1_K0 0x5a827999
|
||||
#define SHA1_K20 0x6ed9eba1
|
||||
#define SHA1_K40 0x8f1bbcdc
|
||||
#define SHA1_K60 0xca62c1d6
|
||||
|
||||
const uint8_t sha1InitState[] = {
|
||||
0x01,0x23,0x45,0x67, // H0
|
||||
0x89,0xab,0xcd,0xef, // H1
|
||||
0xfe,0xdc,0xba,0x98, // H2
|
||||
0x76,0x54,0x32,0x10, // H3
|
||||
0xf0,0xe1,0xd2,0xc3 // H4
|
||||
};
|
||||
|
||||
static uint32_t sha1_rol32(uint32_t number, uint8_t bits) {
|
||||
return ((number << bits) | (number >> (32-bits)));
|
||||
}
|
||||
|
||||
static void sha1_hashBlock(struct SHA1_CTX *s) {
|
||||
uint8_t i;
|
||||
uint32_t a,b,c,d,e,t;
|
||||
|
||||
a=s->state.w[0];
|
||||
b=s->state.w[1];
|
||||
c=s->state.w[2];
|
||||
d=s->state.w[3];
|
||||
e=s->state.w[4];
|
||||
for (i=0; i<80; i++) {
|
||||
if (i>=16) {
|
||||
t = s->buffer.w[(i+13)&15] ^ s->buffer.w[(i+8)&15] ^ s->buffer.w[(i+2)&15] ^ s->buffer.w[i&15];
|
||||
s->buffer.w[i&15] = sha1_rol32(t,1);
|
||||
}
|
||||
if (i<20) {
|
||||
t = (d ^ (b & (c ^ d))) + SHA1_K0;
|
||||
} else if (i<40) {
|
||||
t = (b ^ c ^ d) + SHA1_K20;
|
||||
} else if (i<60) {
|
||||
t = ((b & c) | (d & (b | c))) + SHA1_K40;
|
||||
} else {
|
||||
t = (b ^ c ^ d) + SHA1_K60;
|
||||
}
|
||||
t+=sha1_rol32(a,5) + e + s->buffer.w[i&15];
|
||||
e=d;
|
||||
d=c;
|
||||
c=sha1_rol32(b,30);
|
||||
b=a;
|
||||
a=t;
|
||||
}
|
||||
s->state.w[0] += a;
|
||||
s->state.w[1] += b;
|
||||
s->state.w[2] += c;
|
||||
s->state.w[3] += d;
|
||||
s->state.w[4] += e;
|
||||
}
|
||||
|
||||
static void sha1_addUncounted(struct SHA1_CTX *s, uint8_t data) {
|
||||
s->buffer.b[s->bufferOffset ^ 3] = data;
|
||||
s->bufferOffset++;
|
||||
if (s->bufferOffset == BLOCK_LENGTH) {
|
||||
sha1_hashBlock(s);
|
||||
s->bufferOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void sha1_writebyte(struct SHA1_CTX *s, uint8_t data) {
|
||||
++s->byteCount;
|
||||
sha1_addUncounted(s, data);
|
||||
}
|
||||
|
||||
static void sha1_pad(struct SHA1_CTX *s) {
|
||||
// Implement SHA-1 padding (fips180-2 §5.1.1)
|
||||
|
||||
// Pad with 0x80 followed by 0x00 until the end of the block
|
||||
sha1_addUncounted(s, 0x80);
|
||||
while (s->bufferOffset != 56) sha1_addUncounted(s, 0x00);
|
||||
|
||||
// Append length in the last 8 bytes
|
||||
sha1_addUncounted(s, 0); // We're only using 32 bit lengths
|
||||
sha1_addUncounted(s, 0); // But SHA-1 supports 64 bit lengths
|
||||
sha1_addUncounted(s, 0); // So zero pad the top bits
|
||||
sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8
|
||||
sha1_addUncounted(s, s->byteCount >> 21); // as SHA-1 supports bitstreams as well as
|
||||
sha1_addUncounted(s, s->byteCount >> 13); // byte.
|
||||
sha1_addUncounted(s, s->byteCount >> 5);
|
||||
sha1_addUncounted(s, s->byteCount << 3);
|
||||
}
|
||||
|
||||
int SHA1_Init(struct SHA1_CTX **s) {
|
||||
*s = malloc(sizeof(struct SHA1_CTX));
|
||||
if (!*s) {
|
||||
return 0;
|
||||
}
|
||||
memcpy((*s)->state.b, sha1InitState, SHA1_LENGTH);
|
||||
(*s)->byteCount = 0;
|
||||
(*s)->bufferOffset = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void SHA1_Update(struct SHA1_CTX *s, const void *data, size_t len) {
|
||||
const uint8_t *bytes = data;
|
||||
for (;len--;) sha1_writebyte(s, *bytes++);
|
||||
}
|
||||
|
||||
void SHA1_Final(struct SHA1_CTX *s, unsigned char* result) {
|
||||
int i;
|
||||
// Pad to complete the last block
|
||||
sha1_pad(s);
|
||||
|
||||
// Swap byte order back
|
||||
for (i=0; i<5; i++) {
|
||||
uint32_t a,b;
|
||||
a=s->state.w[i];
|
||||
b=a<<24;
|
||||
b|=(a<<8) & 0x00ff0000;
|
||||
b|=(a>>8) & 0x0000ff00;
|
||||
b|=a>>24;
|
||||
s->state.w[i]=b;
|
||||
}
|
||||
|
||||
// Return pointer to hash (20 characters)
|
||||
memcpy(result, s->state.b, sizeof(s->state.b));
|
||||
}
|
||||
|
||||
void SHA1_Free(struct SHA1_CTX** s) {
|
||||
if (!s || !*s) {
|
||||
return;
|
||||
}
|
||||
free(*s);
|
||||
*s = NULL;
|
||||
}
|
28
src/sha1.h
28
src/sha1.h
|
@ -1,28 +0,0 @@
|
|||
/* This code is public-domain - it is based on libcrypt
|
||||
* placed in the public domain by Wei Dai and other contributors.
|
||||
*/
|
||||
|
||||
#ifndef INTERNAL_SHA1_H
|
||||
#define INTERNAL_SHA1_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define SHA1_LENGTH 20
|
||||
|
||||
struct SHA1_CTX;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int SHA1_Init(struct SHA1_CTX **s);
|
||||
void SHA1_Update(struct SHA1_CTX *s, const void *data, size_t len);
|
||||
void SHA1_Final(struct SHA1_CTX *s, uint8_t *result);
|
||||
void SHA1_Free(struct SHA1_CTX **s);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* INTERNAL_SHA1_H */
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
#include "FatalException.h"
|
||||
#include "util.h"
|
||||
#include "crypto_endian.h"
|
||||
|
||||
namespace {
|
||||
using namespace aria2;
|
||||
|
@ -156,13 +157,6 @@ HMACResult PBKDF2(HMAC* hmac,
|
|||
if (key_length == 0) {
|
||||
key_length = hmac_length;
|
||||
}
|
||||
typedef union
|
||||
{
|
||||
uint8_t bytes[4];
|
||||
uint32_t count;
|
||||
} counter_t;
|
||||
counter_t counter, swapped;
|
||||
counter.count = 1;
|
||||
|
||||
auto work = make_unique<char[]>(hmac_length);
|
||||
char* p = work.get();
|
||||
|
@ -170,10 +164,10 @@ HMACResult PBKDF2(HMAC* hmac,
|
|||
|
||||
hmac->reset();
|
||||
|
||||
while (key_length) {
|
||||
for (uint32_t counter = 1; key_length; ++counter) {
|
||||
hmac->update(salt, salt_length);
|
||||
swapped.count = htonl(counter.count++);
|
||||
hmac->update((char*)swapped.bytes, sizeof(swapped.bytes));
|
||||
const uint32_t c = crypto::__crypto_be(counter);
|
||||
hmac->update((char*)&c, sizeof(c));
|
||||
|
||||
auto bytes = hmac->getResult().getBytes();
|
||||
memcpy(p, bytes.data(), bytes.length());
|
||||
|
|
|
@ -685,20 +685,14 @@ void HttpResponseTest::testGetDigest()
|
|||
"MD5=LJDK2+9ClF8Nz/K5WZd/+A==");
|
||||
std::vector<Checksum> result;
|
||||
httpResponse.getDigest(result);
|
||||
#ifdef USE_INTERNAL_MD
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)2, result.size());
|
||||
#else // USE_INTERNAL_MD
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)3, result.size());
|
||||
#endif // USE_INTERNAL_MD
|
||||
|
||||
Checksum c = result[0];
|
||||
#ifndef USE_INTERNAL_MD
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("sha-256"), c.getHashType());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("f83f271ae773dc6fe4a6454a41e0eb237c43e7bbf451e426cc60993a4d379ec5"),
|
||||
util::toHex(c.getDigest()));
|
||||
|
||||
c = result[1];
|
||||
#endif
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), c.getHashType());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("f36003f22b462ffa184390533c500d8989e9f681"),
|
||||
util::toHex(c.getDigest()));
|
||||
|
|
Loading…
Reference in New Issue