Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:02:08

0001 /*
0002  * This RFC 1321 compatible MD5 implementation originated at:
0003  * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
0004  *
0005  * Author:
0006  * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
0007  *
0008  * This software was written by Alexander Peslyak in 2001.  No copyright is
0009  * claimed, and the software is hereby placed in the public domain.
0010  * In case this attempt to disclaim copyright and place the software in the
0011  * public domain is deemed null and void, then the software is
0012  * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
0013  * general public under the following terms:
0014  *
0015  * Redistribution and use in source and binary forms, with or without
0016  * modification, are permitted.
0017  *
0018  * There's ABSOLUTELY NO WARRANTY, express or implied.
0019  *
0020  */
0021 
0022 // Distributed under the Boost Software License, Version 1.0. (See
0023 // accompanying file LICENSE_1_0.txt or copy at
0024 // https://www.boost.org/LICENSE_1_0.txt)
0025 
0026 #ifndef BOOST_UUID_MD5_HPP
0027 #define BOOST_UUID_MD5_HPP
0028 
0029 #include <boost/cast.hpp>
0030 #include <boost/config.hpp>
0031 #include <boost/cstdint.hpp>
0032 #include <boost/uuid/uuid.hpp> // for version
0033 #include <boost/predef/other/endian.h>
0034 #include <string.h>
0035 
0036 namespace boost {
0037 namespace uuids {
0038 namespace detail {
0039 
0040 class md5
0041 {
0042 public:
0043     typedef unsigned int(digest_type)[4];
0044 
0045     md5()
0046     {
0047         MD5_Init(&ctx_);
0048     }
0049 
0050     void process_byte(unsigned char byte)
0051     {
0052         MD5_Update(&ctx_, &byte, 1);
0053     }
0054 
0055     void process_bytes(void const* buffer, std::size_t byte_count)
0056     {
0057         MD5_Update(&ctx_, buffer, boost::numeric_cast<unsigned long>(byte_count));
0058     }
0059 
0060     void get_digest(digest_type& digest)
0061     {
0062         MD5_Final(reinterpret_cast<unsigned char *>(&digest[0]), &ctx_);
0063     }
0064 
0065     unsigned char get_version() const
0066     {
0067         // RFC 4122 Section 4.1.3
0068         return uuid::version_name_based_md5;
0069     }
0070 
0071 private:
0072 
0073     /* Any 32-bit or wider unsigned integer data type will do */
0074     typedef uint32_t MD5_u32plus;
0075 
0076     typedef struct {
0077         MD5_u32plus lo, hi;
0078         MD5_u32plus a, b, c, d;
0079         unsigned char buffer[64];
0080         MD5_u32plus block[16];
0081     } MD5_CTX;
0082 
0083     /*
0084      * The basic MD5 functions.
0085      *
0086      * F and G are optimized compared to their RFC 1321 definitions for
0087      * architectures that lack an AND-NOT instruction, just like in Colin Plumb's
0088      * implementation.
0089      */
0090     BOOST_FORCEINLINE MD5_u32plus BOOST_UUID_DETAIL_MD5_F(MD5_u32plus x, MD5_u32plus y, MD5_u32plus z) { return ((z) ^ ((x) & ((y) ^ (z)))); }
0091     BOOST_FORCEINLINE MD5_u32plus BOOST_UUID_DETAIL_MD5_G(MD5_u32plus x, MD5_u32plus y, MD5_u32plus z) { return ((y) ^ ((z) & ((x) ^ (y)))); }
0092     BOOST_FORCEINLINE MD5_u32plus BOOST_UUID_DETAIL_MD5_H(MD5_u32plus x, MD5_u32plus y, MD5_u32plus z) { return (((x) ^ (y)) ^ (z)); }
0093     BOOST_FORCEINLINE MD5_u32plus BOOST_UUID_DETAIL_MD5_H2(MD5_u32plus x, MD5_u32plus y, MD5_u32plus z) { return ((x) ^ ((y) ^ (z))); }
0094     BOOST_FORCEINLINE MD5_u32plus BOOST_UUID_DETAIL_MD5_I(MD5_u32plus x, MD5_u32plus y, MD5_u32plus z) { return ((y) ^ ((x) | ~(z))); }
0095 
0096     /*
0097      * The MD5 transformation for all four rounds.
0098      */
0099     #define BOOST_UUID_DETAIL_MD5_STEP(f, a, b, c, d, x, t, s) \
0100         (a) += f((b), (c), (d)) + (x) + (t); \
0101         (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
0102         (a) += (b);
0103 
0104     /*
0105      * SET reads 4 input bytes in little-endian byte order and stores them in a
0106      * properly aligned word in host byte order.
0107      *
0108      * The check for little-endian architectures that tolerate unaligned memory
0109      * accesses is just an optimization.  Nothing will break if it fails to detect
0110      * a suitable architecture.
0111      *
0112      * Unfortunately, this optimization may be a C strict aliasing rules violation
0113      * if the caller's data buffer has effective type that cannot be aliased by
0114      * MD5_u32plus.  In practice, this problem may occur if these MD5 routines are
0115      * inlined into a calling function, or with future and dangerously advanced
0116      * link-time optimizations.  For the time being, keeping these MD5 routines in
0117      * their own translation unit avoids the problem.
0118      */
0119     #if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
0120     #define BOOST_UUID_DETAIL_MD5_SET(n) \
0121         (*(MD5_u32plus *)&ptr[(n) * 4])
0122     #define BOOST_UUID_DETAIL_MD5_GET(n) \
0123         BOOST_UUID_DETAIL_MD5_SET(n)
0124     #else
0125     #define BOOST_UUID_DETAIL_MD5_SET(n) \
0126         (ctx->block[(n)] = \
0127         (MD5_u32plus)ptr[(n) * 4] | \
0128         ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
0129         ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
0130         ((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
0131     #define BOOST_UUID_DETAIL_MD5_GET(n) \
0132         (ctx->block[(n)])
0133     #endif
0134 
0135     /*
0136      * This processes one or more 64-byte data blocks, but does NOT update the bit
0137      * counters.  There are no alignment requirements.
0138      */
0139     const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
0140     {
0141         const unsigned char *ptr;
0142         MD5_u32plus a, b, c, d;
0143         MD5_u32plus saved_a, saved_b, saved_c, saved_d;
0144 
0145         ptr = (const unsigned char *)data;
0146 
0147         a = ctx->a;
0148         b = ctx->b;
0149         c = ctx->c;
0150         d = ctx->d;
0151 
0152         do {
0153             saved_a = a;
0154             saved_b = b;
0155             saved_c = c;
0156             saved_d = d;
0157 
0158     /* Round 1 */
0159             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, a, b, c, d, BOOST_UUID_DETAIL_MD5_SET(0), 0xd76aa478, 7)
0160             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, d, a, b, c, BOOST_UUID_DETAIL_MD5_SET(1), 0xe8c7b756, 12)
0161             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, c, d, a, b, BOOST_UUID_DETAIL_MD5_SET(2), 0x242070db, 17)
0162             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, b, c, d, a, BOOST_UUID_DETAIL_MD5_SET(3), 0xc1bdceee, 22)
0163             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, a, b, c, d, BOOST_UUID_DETAIL_MD5_SET(4), 0xf57c0faf, 7)
0164             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, d, a, b, c, BOOST_UUID_DETAIL_MD5_SET(5), 0x4787c62a, 12)
0165             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, c, d, a, b, BOOST_UUID_DETAIL_MD5_SET(6), 0xa8304613, 17)
0166             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, b, c, d, a, BOOST_UUID_DETAIL_MD5_SET(7), 0xfd469501, 22)
0167             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, a, b, c, d, BOOST_UUID_DETAIL_MD5_SET(8), 0x698098d8, 7)
0168             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, d, a, b, c, BOOST_UUID_DETAIL_MD5_SET(9), 0x8b44f7af, 12)
0169             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, c, d, a, b, BOOST_UUID_DETAIL_MD5_SET(10), 0xffff5bb1, 17)
0170             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, b, c, d, a, BOOST_UUID_DETAIL_MD5_SET(11), 0x895cd7be, 22)
0171             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, a, b, c, d, BOOST_UUID_DETAIL_MD5_SET(12), 0x6b901122, 7)
0172             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, d, a, b, c, BOOST_UUID_DETAIL_MD5_SET(13), 0xfd987193, 12)
0173             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, c, d, a, b, BOOST_UUID_DETAIL_MD5_SET(14), 0xa679438e, 17)
0174             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, b, c, d, a, BOOST_UUID_DETAIL_MD5_SET(15), 0x49b40821, 22)
0175 
0176     /* Round 2 */
0177             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, a, b, c, d, BOOST_UUID_DETAIL_MD5_GET(1), 0xf61e2562, 5)
0178             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, d, a, b, c, BOOST_UUID_DETAIL_MD5_GET(6), 0xc040b340, 9)
0179             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, c, d, a, b, BOOST_UUID_DETAIL_MD5_GET(11), 0x265e5a51, 14)
0180             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, b, c, d, a, BOOST_UUID_DETAIL_MD5_GET(0), 0xe9b6c7aa, 20)
0181             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, a, b, c, d, BOOST_UUID_DETAIL_MD5_GET(5), 0xd62f105d, 5)
0182             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, d, a, b, c, BOOST_UUID_DETAIL_MD5_GET(10), 0x02441453, 9)
0183             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, c, d, a, b, BOOST_UUID_DETAIL_MD5_GET(15), 0xd8a1e681, 14)
0184             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, b, c, d, a, BOOST_UUID_DETAIL_MD5_GET(4), 0xe7d3fbc8, 20)
0185             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, a, b, c, d, BOOST_UUID_DETAIL_MD5_GET(9), 0x21e1cde6, 5)
0186             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, d, a, b, c, BOOST_UUID_DETAIL_MD5_GET(14), 0xc33707d6, 9)
0187             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, c, d, a, b, BOOST_UUID_DETAIL_MD5_GET(3), 0xf4d50d87, 14)
0188             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, b, c, d, a, BOOST_UUID_DETAIL_MD5_GET(8), 0x455a14ed, 20)
0189             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, a, b, c, d, BOOST_UUID_DETAIL_MD5_GET(13), 0xa9e3e905, 5)
0190             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, d, a, b, c, BOOST_UUID_DETAIL_MD5_GET(2), 0xfcefa3f8, 9)
0191             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, c, d, a, b, BOOST_UUID_DETAIL_MD5_GET(7), 0x676f02d9, 14)
0192             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, b, c, d, a, BOOST_UUID_DETAIL_MD5_GET(12), 0x8d2a4c8a, 20)
0193 
0194     /* Round 3 */
0195             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H, a, b, c, d, BOOST_UUID_DETAIL_MD5_GET(5), 0xfffa3942, 4)
0196             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H2, d, a, b, c, BOOST_UUID_DETAIL_MD5_GET(8), 0x8771f681, 11)
0197             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H, c, d, a, b, BOOST_UUID_DETAIL_MD5_GET(11), 0x6d9d6122, 16)
0198             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H2, b, c, d, a, BOOST_UUID_DETAIL_MD5_GET(14), 0xfde5380c, 23)
0199             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H, a, b, c, d, BOOST_UUID_DETAIL_MD5_GET(1), 0xa4beea44, 4)
0200             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H2, d, a, b, c, BOOST_UUID_DETAIL_MD5_GET(4), 0x4bdecfa9, 11)
0201             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H, c, d, a, b, BOOST_UUID_DETAIL_MD5_GET(7), 0xf6bb4b60, 16)
0202             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H2, b, c, d, a, BOOST_UUID_DETAIL_MD5_GET(10), 0xbebfbc70, 23)
0203             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H, a, b, c, d, BOOST_UUID_DETAIL_MD5_GET(13), 0x289b7ec6, 4)
0204             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H2, d, a, b, c, BOOST_UUID_DETAIL_MD5_GET(0), 0xeaa127fa, 11)
0205             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H, c, d, a, b, BOOST_UUID_DETAIL_MD5_GET(3), 0xd4ef3085, 16)
0206             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H2, b, c, d, a, BOOST_UUID_DETAIL_MD5_GET(6), 0x04881d05, 23)
0207             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H, a, b, c, d, BOOST_UUID_DETAIL_MD5_GET(9), 0xd9d4d039, 4)
0208             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H2, d, a, b, c, BOOST_UUID_DETAIL_MD5_GET(12), 0xe6db99e5, 11)
0209             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H, c, d, a, b, BOOST_UUID_DETAIL_MD5_GET(15), 0x1fa27cf8, 16)
0210             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H2, b, c, d, a, BOOST_UUID_DETAIL_MD5_GET(2), 0xc4ac5665, 23)
0211 
0212     /* Round 4 */
0213             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, a, b, c, d, BOOST_UUID_DETAIL_MD5_GET(0), 0xf4292244, 6)
0214             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, d, a, b, c, BOOST_UUID_DETAIL_MD5_GET(7), 0x432aff97, 10)
0215             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, c, d, a, b, BOOST_UUID_DETAIL_MD5_GET(14), 0xab9423a7, 15)
0216             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, b, c, d, a, BOOST_UUID_DETAIL_MD5_GET(5), 0xfc93a039, 21)
0217             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, a, b, c, d, BOOST_UUID_DETAIL_MD5_GET(12), 0x655b59c3, 6)
0218             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, d, a, b, c, BOOST_UUID_DETAIL_MD5_GET(3), 0x8f0ccc92, 10)
0219             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, c, d, a, b, BOOST_UUID_DETAIL_MD5_GET(10), 0xffeff47d, 15)
0220             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, b, c, d, a, BOOST_UUID_DETAIL_MD5_GET(1), 0x85845dd1, 21)
0221             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, a, b, c, d, BOOST_UUID_DETAIL_MD5_GET(8), 0x6fa87e4f, 6)
0222             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, d, a, b, c, BOOST_UUID_DETAIL_MD5_GET(15), 0xfe2ce6e0, 10)
0223             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, c, d, a, b, BOOST_UUID_DETAIL_MD5_GET(6), 0xa3014314, 15)
0224             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, b, c, d, a, BOOST_UUID_DETAIL_MD5_GET(13), 0x4e0811a1, 21)
0225             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, a, b, c, d, BOOST_UUID_DETAIL_MD5_GET(4), 0xf7537e82, 6)
0226             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, d, a, b, c, BOOST_UUID_DETAIL_MD5_GET(11), 0xbd3af235, 10)
0227             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, c, d, a, b, BOOST_UUID_DETAIL_MD5_GET(2), 0x2ad7d2bb, 15)
0228             BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, b, c, d, a, BOOST_UUID_DETAIL_MD5_GET(9), 0xeb86d391, 21)
0229 
0230             a += saved_a;
0231             b += saved_b;
0232             c += saved_c;
0233             d += saved_d;
0234 
0235             ptr += 64;
0236         } while (size -= 64);
0237 
0238         ctx->a = a;
0239         ctx->b = b;
0240         ctx->c = c;
0241         ctx->d = d;
0242 
0243         return ptr;
0244     }
0245 
0246     void MD5_Init(MD5_CTX *ctx)
0247     {
0248         ctx->a = 0x67452301;
0249         ctx->b = 0xefcdab89;
0250         ctx->c = 0x98badcfe;
0251         ctx->d = 0x10325476;
0252 
0253         ctx->lo = 0;
0254         ctx->hi = 0;
0255     }
0256 
0257     void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
0258     {
0259         MD5_u32plus saved_lo;
0260         unsigned long used, available;
0261 
0262         saved_lo = ctx->lo;
0263         if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
0264             ctx->hi++;
0265         ctx->hi += size >> 29;
0266 
0267         used = saved_lo & 0x3f;
0268 
0269         if (used) {
0270             available = 64 - used;
0271 
0272             if (size < available) {
0273                 memcpy(&ctx->buffer[used], data, size);
0274                 return;
0275             }
0276 
0277             memcpy(&ctx->buffer[used], data, available);
0278             data = (const unsigned char *)data + available;
0279             size -= available;
0280             body(ctx, ctx->buffer, 64);
0281         }
0282 
0283         if (size >= 64) {
0284             data = body(ctx, data, size & ~(unsigned long)0x3f);
0285             size &= 0x3f;
0286         }
0287 
0288         memcpy(ctx->buffer, data, size);
0289     }
0290 
0291     // This must remain consistent no matter the endianness
0292     #define BOOST_UUID_DETAIL_MD5_OUT(dst, src) \
0293         (dst)[0] = (unsigned char)(src); \
0294         (dst)[1] = (unsigned char)((src) >> 8); \
0295         (dst)[2] = (unsigned char)((src) >> 16); \
0296         (dst)[3] = (unsigned char)((src) >> 24);
0297 
0298     //
0299     // A big-endian issue with MD5 results was resolved
0300     // in boost 1.71.  If you generated md5 name-based uuids
0301     // with boost 1.66 through 1.70 and stored them, then
0302     // set the following compatibility flag to ensure that
0303     // your hash generation remains consistent.
0304     //
0305 #if defined(BOOST_UUID_COMPAT_PRE_1_71_MD5)
0306     #define BOOST_UUID_DETAIL_MD5_BYTE_OUT(dst, src) \
0307         BOOST_UUID_DETAIL_MD5_OUT(dst, src)
0308 #else
0309     //
0310     // We're copying into a byte buffer which is actually
0311     // backed by an unsigned int array, which later on
0312     // is then swabbed one more time by the basic name
0313     // generator.  Therefore the logic here is reversed.
0314     // This was done to minimize the impact to existing
0315     // name-based hash generation.  The correct fix would
0316     // be to make this and name generation endian-correct
0317     // but that would even break previously generated sha1
0318     // hashes too.
0319     //
0320 #if BOOST_ENDIAN_LITTLE_BYTE
0321     #define BOOST_UUID_DETAIL_MD5_BYTE_OUT(dst, src) \
0322         (dst)[0] = (unsigned char)((src) >> 24); \
0323         (dst)[1] = (unsigned char)((src) >> 16); \
0324         (dst)[2] = (unsigned char)((src) >> 8); \
0325         (dst)[3] = (unsigned char)(src);
0326 #else
0327     #define BOOST_UUID_DETAIL_MD5_BYTE_OUT(dst, src) \
0328         (dst)[0] = (unsigned char)(src); \
0329         (dst)[1] = (unsigned char)((src) >> 8); \
0330         (dst)[2] = (unsigned char)((src) >> 16); \
0331         (dst)[3] = (unsigned char)((src) >> 24);
0332 #endif
0333 #endif // BOOST_UUID_COMPAT_PRE_1_71_MD5
0334 
0335     void MD5_Final(unsigned char *result, MD5_CTX *ctx)
0336     {
0337         unsigned long used, available;
0338 
0339         used = ctx->lo & 0x3f;
0340 
0341         ctx->buffer[used++] = 0x80;
0342 
0343         available = 64 - used;
0344 
0345         if (available < 8) {
0346             memset(&ctx->buffer[used], 0, available);
0347             body(ctx, ctx->buffer, 64);
0348             used = 0;
0349             available = 64;
0350         }
0351 
0352         memset(&ctx->buffer[used], 0, available - 8);
0353 
0354         ctx->lo <<= 3;
0355         BOOST_UUID_DETAIL_MD5_OUT(&ctx->buffer[56], ctx->lo)
0356         BOOST_UUID_DETAIL_MD5_OUT(&ctx->buffer[60], ctx->hi)
0357 
0358         body(ctx, ctx->buffer, 64);
0359 
0360         BOOST_UUID_DETAIL_MD5_BYTE_OUT(&result[0], ctx->a)
0361         BOOST_UUID_DETAIL_MD5_BYTE_OUT(&result[4], ctx->b)
0362         BOOST_UUID_DETAIL_MD5_BYTE_OUT(&result[8], ctx->c)
0363         BOOST_UUID_DETAIL_MD5_BYTE_OUT(&result[12], ctx->d)
0364 
0365         memset(ctx, 0, sizeof(*ctx));
0366     }
0367 
0368 #undef BOOST_UUID_DETAIL_MD5_OUT
0369 #undef BOOST_UUID_DETAIL_MD5_SET
0370 #undef BOOST_UUID_DETAIL_MD5_GET
0371 #undef BOOST_UUID_DETAIL_MD5_STEP
0372 
0373     MD5_CTX ctx_;
0374 };
0375 
0376 
0377 } // detail
0378 } // uuids
0379 } // boost
0380 
0381 #endif // BOOST_UUID_MD5_HPP