LLVM API Documentation

MD5.cpp
Go to the documentation of this file.
00001 /*
00002  * This code is derived from (original license follows):
00003  *
00004  * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
00005  * MD5 Message-Digest Algorithm (RFC 1321).
00006  *
00007  * Homepage:
00008  * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
00009  *
00010  * Author:
00011  * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
00012  *
00013  * This software was written by Alexander Peslyak in 2001.  No copyright is
00014  * claimed, and the software is hereby placed in the public domain.
00015  * In case this attempt to disclaim copyright and place the software in the
00016  * public domain is deemed null and void, then the software is
00017  * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
00018  * general public under the following terms:
00019  *
00020  * Redistribution and use in source and binary forms, with or without
00021  * modification, are permitted.
00022  *
00023  * There's ABSOLUTELY NO WARRANTY, express or implied.
00024  *
00025  * (This is a heavily cut-down "BSD license".)
00026  *
00027  * This differs from Colin Plumb's older public domain implementation in that
00028  * no exactly 32-bit integer data type is required (any 32-bit or wider
00029  * unsigned integer data type will do), there's no compile-time endianness
00030  * configuration, and the function prototypes match OpenSSL's.  No code from
00031  * Colin Plumb's implementation has been reused; this comment merely compares
00032  * the properties of the two independent implementations.
00033  *
00034  * The primary goals of this implementation are portability and ease of use.
00035  * It is meant to be fast, but not as fast as possible.  Some known
00036  * optimizations are not included to reduce source code size and avoid
00037  * compile-time configuration.
00038  */
00039 
00040 #include "llvm/ADT/ArrayRef.h"
00041 #include "llvm/Support/Format.h"
00042 #include "llvm/Support/MD5.h"
00043 #include "llvm/Support/raw_ostream.h"
00044 #include <cstring>
00045 
00046 // The basic MD5 functions.
00047 
00048 // F and G are optimized compared to their RFC 1321 definitions for
00049 // architectures that lack an AND-NOT instruction, just like in Colin Plumb's
00050 // implementation.
00051 #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
00052 #define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
00053 #define H(x, y, z) ((x) ^ (y) ^ (z))
00054 #define I(x, y, z) ((y) ^ ((x) | ~(z)))
00055 
00056 // The MD5 transformation for all four rounds.
00057 #define STEP(f, a, b, c, d, x, t, s)                                           \
00058   (a) += f((b), (c), (d)) + (x) + (t);                                         \
00059   (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s))));                   \
00060   (a) += (b);
00061 
00062 // SET reads 4 input bytes in little-endian byte order and stores them
00063 // in a properly aligned word in host byte order.
00064 #define SET(n)                                                                 \
00065   (block[(n)] =                                                                \
00066        (MD5_u32plus) ptr[(n) * 4] | ((MD5_u32plus) ptr[(n) * 4 + 1] << 8) |    \
00067        ((MD5_u32plus) ptr[(n) * 4 + 2] << 16) |                                \
00068        ((MD5_u32plus) ptr[(n) * 4 + 3] << 24))
00069 #define GET(n) (block[(n)])
00070 
00071 namespace llvm {
00072 
00073 /// \brief This processes one or more 64-byte data blocks, but does NOT update
00074 ///the bit counters.  There are no alignment requirements.
00075 const uint8_t *MD5::body(ArrayRef<uint8_t> Data) {
00076   const uint8_t *ptr;
00077   MD5_u32plus a, b, c, d;
00078   MD5_u32plus saved_a, saved_b, saved_c, saved_d;
00079   unsigned long Size = Data.size();
00080 
00081   ptr = Data.data();
00082 
00083   a = this->a;
00084   b = this->b;
00085   c = this->c;
00086   d = this->d;
00087 
00088   do {
00089     saved_a = a;
00090     saved_b = b;
00091     saved_c = c;
00092     saved_d = d;
00093 
00094     // Round 1
00095     STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
00096     STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
00097     STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
00098     STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
00099     STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
00100     STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
00101     STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
00102     STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
00103     STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
00104     STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
00105     STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
00106     STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
00107     STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
00108     STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
00109     STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
00110     STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
00111 
00112     // Round 2
00113     STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
00114     STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
00115     STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
00116     STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
00117     STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
00118     STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
00119     STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
00120     STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
00121     STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
00122     STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
00123     STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
00124     STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
00125     STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
00126     STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
00127     STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
00128     STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
00129 
00130     // Round 3
00131     STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
00132     STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
00133     STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
00134     STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
00135     STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
00136     STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
00137     STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
00138     STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
00139     STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
00140     STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
00141     STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
00142     STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
00143     STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
00144     STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
00145     STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
00146     STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
00147 
00148     // Round 4
00149     STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
00150     STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
00151     STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
00152     STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
00153     STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
00154     STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
00155     STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
00156     STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
00157     STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
00158     STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
00159     STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
00160     STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
00161     STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
00162     STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
00163     STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
00164     STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
00165 
00166     a += saved_a;
00167     b += saved_b;
00168     c += saved_c;
00169     d += saved_d;
00170 
00171     ptr += 64;
00172   } while (Size -= 64);
00173 
00174   this->a = a;
00175   this->b = b;
00176   this->c = c;
00177   this->d = d;
00178 
00179   return ptr;
00180 }
00181 
00182 MD5::MD5()
00183     : a(0x67452301), b(0xefcdab89), c(0x98badcfe), d(0x10325476), hi(0), lo(0) {
00184 }
00185 
00186 /// Incrementally add the bytes in \p Data to the hash.
00187 void MD5::update(ArrayRef<uint8_t> Data) {
00188   MD5_u32plus saved_lo;
00189   unsigned long used, free;
00190   const uint8_t *Ptr = Data.data();
00191   unsigned long Size = Data.size();
00192 
00193   saved_lo = lo;
00194   if ((lo = (saved_lo + Size) & 0x1fffffff) < saved_lo)
00195     hi++;
00196   hi += Size >> 29;
00197 
00198   used = saved_lo & 0x3f;
00199 
00200   if (used) {
00201     free = 64 - used;
00202 
00203     if (Size < free) {
00204       memcpy(&buffer[used], Ptr, Size);
00205       return;
00206     }
00207 
00208     memcpy(&buffer[used], Ptr, free);
00209     Ptr = Ptr + free;
00210     Size -= free;
00211     body(makeArrayRef(buffer, 64));
00212   }
00213 
00214   if (Size >= 64) {
00215     Ptr = body(makeArrayRef(Ptr, Size & ~(unsigned long) 0x3f));
00216     Size &= 0x3f;
00217   }
00218 
00219   memcpy(buffer, Ptr, Size);
00220 }
00221 
00222 /// Add the bytes in the StringRef \p Str to the hash.
00223 // Note that this isn't a string and so this won't include any trailing NULL
00224 // bytes.
00225 void MD5::update(StringRef Str) {
00226   ArrayRef<uint8_t> SVal((const uint8_t *)Str.data(), Str.size());
00227   update(SVal);
00228 }
00229 
00230 /// \brief Finish the hash and place the resulting hash into \p result.
00231 /// \param result is assumed to be a minimum of 16-bytes in size.
00232 void MD5::final(MD5Result &result) {
00233   unsigned long used, free;
00234 
00235   used = lo & 0x3f;
00236 
00237   buffer[used++] = 0x80;
00238 
00239   free = 64 - used;
00240 
00241   if (free < 8) {
00242     memset(&buffer[used], 0, free);
00243     body(makeArrayRef(buffer, 64));
00244     used = 0;
00245     free = 64;
00246   }
00247 
00248   memset(&buffer[used], 0, free - 8);
00249 
00250   lo <<= 3;
00251   buffer[56] = lo;
00252   buffer[57] = lo >> 8;
00253   buffer[58] = lo >> 16;
00254   buffer[59] = lo >> 24;
00255   buffer[60] = hi;
00256   buffer[61] = hi >> 8;
00257   buffer[62] = hi >> 16;
00258   buffer[63] = hi >> 24;
00259 
00260   body(makeArrayRef(buffer, 64));
00261 
00262   result[0] = a;
00263   result[1] = a >> 8;
00264   result[2] = a >> 16;
00265   result[3] = a >> 24;
00266   result[4] = b;
00267   result[5] = b >> 8;
00268   result[6] = b >> 16;
00269   result[7] = b >> 24;
00270   result[8] = c;
00271   result[9] = c >> 8;
00272   result[10] = c >> 16;
00273   result[11] = c >> 24;
00274   result[12] = d;
00275   result[13] = d >> 8;
00276   result[14] = d >> 16;
00277   result[15] = d >> 24;
00278 }
00279 
00280 void MD5::stringifyResult(MD5Result &result, SmallString<32> &Str) {
00281   raw_svector_ostream Res(Str);
00282   for (int i = 0; i < 16; ++i)
00283     Res << format("%.2x", result[i]);
00284 }
00285 
00286 }