10b57cec5SDimitry Andric /*
20b57cec5SDimitry Andric * This code is derived from (original license follows):
30b57cec5SDimitry Andric *
40b57cec5SDimitry Andric * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
50b57cec5SDimitry Andric * MD5 Message-Digest Algorithm (RFC 1321).
60b57cec5SDimitry Andric *
70b57cec5SDimitry Andric * Homepage:
80b57cec5SDimitry Andric * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
90b57cec5SDimitry Andric *
100b57cec5SDimitry Andric * Author:
110b57cec5SDimitry Andric * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
120b57cec5SDimitry Andric *
130b57cec5SDimitry Andric * This software was written by Alexander Peslyak in 2001. No copyright is
140b57cec5SDimitry Andric * claimed, and the software is hereby placed in the public domain.
150b57cec5SDimitry Andric * In case this attempt to disclaim copyright and place the software in the
160b57cec5SDimitry Andric * public domain is deemed null and void, then the software is
170b57cec5SDimitry Andric * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
180b57cec5SDimitry Andric * general public under the following terms:
190b57cec5SDimitry Andric *
200b57cec5SDimitry Andric * Redistribution and use in source and binary forms, with or without
210b57cec5SDimitry Andric * modification, are permitted.
220b57cec5SDimitry Andric *
230b57cec5SDimitry Andric * There's ABSOLUTELY NO WARRANTY, express or implied.
240b57cec5SDimitry Andric *
250b57cec5SDimitry Andric * (This is a heavily cut-down "BSD license".)
260b57cec5SDimitry Andric *
270b57cec5SDimitry Andric * This differs from Colin Plumb's older public domain implementation in that
280b57cec5SDimitry Andric * no exactly 32-bit integer data type is required (any 32-bit or wider
290b57cec5SDimitry Andric * unsigned integer data type will do), there's no compile-time endianness
300b57cec5SDimitry Andric * configuration, and the function prototypes match OpenSSL's. No code from
310b57cec5SDimitry Andric * Colin Plumb's implementation has been reused; this comment merely compares
320b57cec5SDimitry Andric * the properties of the two independent implementations.
330b57cec5SDimitry Andric *
340b57cec5SDimitry Andric * The primary goals of this implementation are portability and ease of use.
350b57cec5SDimitry Andric * It is meant to be fast, but not as fast as possible. Some known
360b57cec5SDimitry Andric * optimizations are not included to reduce source code size and avoid
370b57cec5SDimitry Andric * compile-time configuration.
380b57cec5SDimitry Andric */
390b57cec5SDimitry Andric
400b57cec5SDimitry Andric #include "llvm/Support/MD5.h"
410b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
425ffd83dbSDimitry Andric #include "llvm/ADT/SmallString.h"
4304eeddc0SDimitry Andric #include "llvm/ADT/StringExtras.h"
440b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
450b57cec5SDimitry Andric #include "llvm/Support/Endian.h"
460b57cec5SDimitry Andric #include <array>
470b57cec5SDimitry Andric #include <cstdint>
480b57cec5SDimitry Andric #include <cstring>
490b57cec5SDimitry Andric
500b57cec5SDimitry Andric // The basic MD5 functions.
510b57cec5SDimitry Andric
520b57cec5SDimitry Andric // F and G are optimized compared to their RFC 1321 definitions for
530b57cec5SDimitry Andric // architectures that lack an AND-NOT instruction, just like in Colin Plumb's
540b57cec5SDimitry Andric // implementation.
550b57cec5SDimitry Andric #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
560b57cec5SDimitry Andric #define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
570b57cec5SDimitry Andric #define H(x, y, z) ((x) ^ (y) ^ (z))
580b57cec5SDimitry Andric #define I(x, y, z) ((y) ^ ((x) | ~(z)))
590b57cec5SDimitry Andric
600b57cec5SDimitry Andric // The MD5 transformation for all four rounds.
610b57cec5SDimitry Andric #define STEP(f, a, b, c, d, x, t, s) \
620b57cec5SDimitry Andric (a) += f((b), (c), (d)) + (x) + (t); \
630b57cec5SDimitry Andric (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
640b57cec5SDimitry Andric (a) += (b);
650b57cec5SDimitry Andric
660b57cec5SDimitry Andric // SET reads 4 input bytes in little-endian byte order and stores them
670b57cec5SDimitry Andric // in a properly aligned word in host byte order.
680b57cec5SDimitry Andric #define SET(n) \
69349cc55cSDimitry Andric (InternalState.block[(n)] = (MD5_u32plus)ptr[(n)*4] | \
70349cc55cSDimitry Andric ((MD5_u32plus)ptr[(n)*4 + 1] << 8) | \
710b57cec5SDimitry Andric ((MD5_u32plus)ptr[(n)*4 + 2] << 16) | \
720b57cec5SDimitry Andric ((MD5_u32plus)ptr[(n)*4 + 3] << 24))
73349cc55cSDimitry Andric #define GET(n) (InternalState.block[(n)])
740b57cec5SDimitry Andric
750b57cec5SDimitry Andric using namespace llvm;
760b57cec5SDimitry Andric
770b57cec5SDimitry Andric /// This processes one or more 64-byte data blocks, but does NOT update
780b57cec5SDimitry Andric ///the bit counters. There are no alignment requirements.
body(ArrayRef<uint8_t> Data)790b57cec5SDimitry Andric const uint8_t *MD5::body(ArrayRef<uint8_t> Data) {
800b57cec5SDimitry Andric const uint8_t *ptr;
810b57cec5SDimitry Andric MD5_u32plus a, b, c, d;
820b57cec5SDimitry Andric MD5_u32plus saved_a, saved_b, saved_c, saved_d;
830b57cec5SDimitry Andric unsigned long Size = Data.size();
840b57cec5SDimitry Andric
850b57cec5SDimitry Andric ptr = Data.data();
860b57cec5SDimitry Andric
87349cc55cSDimitry Andric a = InternalState.a;
88349cc55cSDimitry Andric b = InternalState.b;
89349cc55cSDimitry Andric c = InternalState.c;
90349cc55cSDimitry Andric d = InternalState.d;
910b57cec5SDimitry Andric
920b57cec5SDimitry Andric do {
930b57cec5SDimitry Andric saved_a = a;
940b57cec5SDimitry Andric saved_b = b;
950b57cec5SDimitry Andric saved_c = c;
960b57cec5SDimitry Andric saved_d = d;
970b57cec5SDimitry Andric
980b57cec5SDimitry Andric // Round 1
990b57cec5SDimitry Andric STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
1000b57cec5SDimitry Andric STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
1010b57cec5SDimitry Andric STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
1020b57cec5SDimitry Andric STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
1030b57cec5SDimitry Andric STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
1040b57cec5SDimitry Andric STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
1050b57cec5SDimitry Andric STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
1060b57cec5SDimitry Andric STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
1070b57cec5SDimitry Andric STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
1080b57cec5SDimitry Andric STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
1090b57cec5SDimitry Andric STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
1100b57cec5SDimitry Andric STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
1110b57cec5SDimitry Andric STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
1120b57cec5SDimitry Andric STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
1130b57cec5SDimitry Andric STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
1140b57cec5SDimitry Andric STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
1150b57cec5SDimitry Andric
1160b57cec5SDimitry Andric // Round 2
1170b57cec5SDimitry Andric STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
1180b57cec5SDimitry Andric STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
1190b57cec5SDimitry Andric STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
1200b57cec5SDimitry Andric STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
1210b57cec5SDimitry Andric STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
1220b57cec5SDimitry Andric STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
1230b57cec5SDimitry Andric STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
1240b57cec5SDimitry Andric STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
1250b57cec5SDimitry Andric STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
1260b57cec5SDimitry Andric STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
1270b57cec5SDimitry Andric STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
1280b57cec5SDimitry Andric STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
1290b57cec5SDimitry Andric STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
1300b57cec5SDimitry Andric STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
1310b57cec5SDimitry Andric STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
1320b57cec5SDimitry Andric STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
1330b57cec5SDimitry Andric
1340b57cec5SDimitry Andric // Round 3
1350b57cec5SDimitry Andric STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
1360b57cec5SDimitry Andric STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
1370b57cec5SDimitry Andric STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
1380b57cec5SDimitry Andric STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
1390b57cec5SDimitry Andric STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
1400b57cec5SDimitry Andric STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
1410b57cec5SDimitry Andric STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
1420b57cec5SDimitry Andric STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
1430b57cec5SDimitry Andric STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
1440b57cec5SDimitry Andric STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
1450b57cec5SDimitry Andric STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
1460b57cec5SDimitry Andric STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
1470b57cec5SDimitry Andric STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
1480b57cec5SDimitry Andric STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
1490b57cec5SDimitry Andric STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
1500b57cec5SDimitry Andric STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
1510b57cec5SDimitry Andric
1520b57cec5SDimitry Andric // Round 4
1530b57cec5SDimitry Andric STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
1540b57cec5SDimitry Andric STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
1550b57cec5SDimitry Andric STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
1560b57cec5SDimitry Andric STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
1570b57cec5SDimitry Andric STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
1580b57cec5SDimitry Andric STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
1590b57cec5SDimitry Andric STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
1600b57cec5SDimitry Andric STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
1610b57cec5SDimitry Andric STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
1620b57cec5SDimitry Andric STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
1630b57cec5SDimitry Andric STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
1640b57cec5SDimitry Andric STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
1650b57cec5SDimitry Andric STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
1660b57cec5SDimitry Andric STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
1670b57cec5SDimitry Andric STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
1680b57cec5SDimitry Andric STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
1690b57cec5SDimitry Andric
1700b57cec5SDimitry Andric a += saved_a;
1710b57cec5SDimitry Andric b += saved_b;
1720b57cec5SDimitry Andric c += saved_c;
1730b57cec5SDimitry Andric d += saved_d;
1740b57cec5SDimitry Andric
1750b57cec5SDimitry Andric ptr += 64;
1760b57cec5SDimitry Andric } while (Size -= 64);
1770b57cec5SDimitry Andric
178349cc55cSDimitry Andric InternalState.a = a;
179349cc55cSDimitry Andric InternalState.b = b;
180349cc55cSDimitry Andric InternalState.c = c;
181349cc55cSDimitry Andric InternalState.d = d;
1820b57cec5SDimitry Andric
1830b57cec5SDimitry Andric return ptr;
1840b57cec5SDimitry Andric }
1850b57cec5SDimitry Andric
1860b57cec5SDimitry Andric MD5::MD5() = default;
1870b57cec5SDimitry Andric
1880b57cec5SDimitry Andric /// Incrementally add the bytes in \p Data to the hash.
update(ArrayRef<uint8_t> Data)1890b57cec5SDimitry Andric void MD5::update(ArrayRef<uint8_t> Data) {
1900b57cec5SDimitry Andric MD5_u32plus saved_lo;
1910b57cec5SDimitry Andric unsigned long used, free;
1920b57cec5SDimitry Andric const uint8_t *Ptr = Data.data();
1930b57cec5SDimitry Andric unsigned long Size = Data.size();
1940b57cec5SDimitry Andric
195349cc55cSDimitry Andric saved_lo = InternalState.lo;
196349cc55cSDimitry Andric if ((InternalState.lo = (saved_lo + Size) & 0x1fffffff) < saved_lo)
197349cc55cSDimitry Andric InternalState.hi++;
198349cc55cSDimitry Andric InternalState.hi += Size >> 29;
1990b57cec5SDimitry Andric
2000b57cec5SDimitry Andric used = saved_lo & 0x3f;
2010b57cec5SDimitry Andric
2020b57cec5SDimitry Andric if (used) {
2030b57cec5SDimitry Andric free = 64 - used;
2040b57cec5SDimitry Andric
2050b57cec5SDimitry Andric if (Size < free) {
206349cc55cSDimitry Andric memcpy(&InternalState.buffer[used], Ptr, Size);
2070b57cec5SDimitry Andric return;
2080b57cec5SDimitry Andric }
2090b57cec5SDimitry Andric
210349cc55cSDimitry Andric memcpy(&InternalState.buffer[used], Ptr, free);
2110b57cec5SDimitry Andric Ptr = Ptr + free;
2120b57cec5SDimitry Andric Size -= free;
213*bdd1243dSDimitry Andric body(ArrayRef(InternalState.buffer, 64));
2140b57cec5SDimitry Andric }
2150b57cec5SDimitry Andric
2160b57cec5SDimitry Andric if (Size >= 64) {
217*bdd1243dSDimitry Andric Ptr = body(ArrayRef(Ptr, Size & ~(unsigned long)0x3f));
2180b57cec5SDimitry Andric Size &= 0x3f;
2190b57cec5SDimitry Andric }
2200b57cec5SDimitry Andric
221349cc55cSDimitry Andric memcpy(InternalState.buffer, Ptr, Size);
2220b57cec5SDimitry Andric }
2230b57cec5SDimitry Andric
2240b57cec5SDimitry Andric /// Add the bytes in the StringRef \p Str to the hash.
2250b57cec5SDimitry Andric // Note that this isn't a string and so this won't include any trailing NULL
2260b57cec5SDimitry Andric // bytes.
update(StringRef Str)2270b57cec5SDimitry Andric void MD5::update(StringRef Str) {
2280b57cec5SDimitry Andric ArrayRef<uint8_t> SVal((const uint8_t *)Str.data(), Str.size());
2290b57cec5SDimitry Andric update(SVal);
2300b57cec5SDimitry Andric }
2310b57cec5SDimitry Andric
2320b57cec5SDimitry Andric /// Finish the hash and place the resulting hash into \p result.
2330b57cec5SDimitry Andric /// \param Result is assumed to be a minimum of 16-bytes in size.
final(MD5Result & Result)2340b57cec5SDimitry Andric void MD5::final(MD5Result &Result) {
2350b57cec5SDimitry Andric unsigned long used, free;
2360b57cec5SDimitry Andric
237349cc55cSDimitry Andric used = InternalState.lo & 0x3f;
2380b57cec5SDimitry Andric
239349cc55cSDimitry Andric InternalState.buffer[used++] = 0x80;
2400b57cec5SDimitry Andric
2410b57cec5SDimitry Andric free = 64 - used;
2420b57cec5SDimitry Andric
2430b57cec5SDimitry Andric if (free < 8) {
244349cc55cSDimitry Andric memset(&InternalState.buffer[used], 0, free);
245*bdd1243dSDimitry Andric body(ArrayRef(InternalState.buffer, 64));
2460b57cec5SDimitry Andric used = 0;
2470b57cec5SDimitry Andric free = 64;
2480b57cec5SDimitry Andric }
2490b57cec5SDimitry Andric
250349cc55cSDimitry Andric memset(&InternalState.buffer[used], 0, free - 8);
2510b57cec5SDimitry Andric
252349cc55cSDimitry Andric InternalState.lo <<= 3;
253349cc55cSDimitry Andric support::endian::write32le(&InternalState.buffer[56], InternalState.lo);
254349cc55cSDimitry Andric support::endian::write32le(&InternalState.buffer[60], InternalState.hi);
2550b57cec5SDimitry Andric
256*bdd1243dSDimitry Andric body(ArrayRef(InternalState.buffer, 64));
2570b57cec5SDimitry Andric
258349cc55cSDimitry Andric support::endian::write32le(&Result[0], InternalState.a);
259349cc55cSDimitry Andric support::endian::write32le(&Result[4], InternalState.b);
260349cc55cSDimitry Andric support::endian::write32le(&Result[8], InternalState.c);
261349cc55cSDimitry Andric support::endian::write32le(&Result[12], InternalState.d);
262349cc55cSDimitry Andric }
263349cc55cSDimitry Andric
final()26481ad6265SDimitry Andric MD5::MD5Result MD5::final() {
26581ad6265SDimitry Andric MD5Result Result;
266349cc55cSDimitry Andric final(Result);
26781ad6265SDimitry Andric return Result;
268349cc55cSDimitry Andric }
269349cc55cSDimitry Andric
result()27081ad6265SDimitry Andric MD5::MD5Result MD5::result() {
271349cc55cSDimitry Andric auto StateToRestore = InternalState;
272349cc55cSDimitry Andric
273349cc55cSDimitry Andric auto Hash = final();
274349cc55cSDimitry Andric
275349cc55cSDimitry Andric // Restore the state
276349cc55cSDimitry Andric InternalState = StateToRestore;
277349cc55cSDimitry Andric
278349cc55cSDimitry Andric return Hash;
2790b57cec5SDimitry Andric }
2800b57cec5SDimitry Andric
digest() const2810b57cec5SDimitry Andric SmallString<32> MD5::MD5Result::digest() const {
2820b57cec5SDimitry Andric SmallString<32> Str;
28381ad6265SDimitry Andric toHex(*this, /*LowerCase*/ true, Str);
2840b57cec5SDimitry Andric return Str;
2850b57cec5SDimitry Andric }
2860b57cec5SDimitry Andric
stringifyResult(MD5Result & Result,SmallVectorImpl<char> & Str)28704eeddc0SDimitry Andric void MD5::stringifyResult(MD5Result &Result, SmallVectorImpl<char> &Str) {
28881ad6265SDimitry Andric toHex(Result, /*LowerCase*/ true, Str);
2890b57cec5SDimitry Andric }
2900b57cec5SDimitry Andric
hash(ArrayRef<uint8_t> Data)29181ad6265SDimitry Andric MD5::MD5Result MD5::hash(ArrayRef<uint8_t> Data) {
2920b57cec5SDimitry Andric MD5 Hash;
2930b57cec5SDimitry Andric Hash.update(Data);
2940b57cec5SDimitry Andric MD5::MD5Result Res;
2950b57cec5SDimitry Andric Hash.final(Res);
2960b57cec5SDimitry Andric
2970b57cec5SDimitry Andric return Res;
2980b57cec5SDimitry Andric }
299