1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
#pragma once
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
/* -*- C++ -*-
* This code is derived from (original license follows):
*
* 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 LLVM_SUPPORT_MD5_H
#define LLVM_SUPPORT_MD5_H
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Endian.h"
#include <array>
#include <cstdint>
namespace llvm {
template <unsigned N> class SmallString;
template <typename T> class ArrayRef;
class MD5 {
public:
struct MD5Result {
std::array<uint8_t, 16> Bytes;
operator std::array<uint8_t, 16>() const { return Bytes; }
const uint8_t &operator[](size_t I) const { return Bytes[I]; }
uint8_t &operator[](size_t I) { return Bytes[I]; }
SmallString<32> digest() const;
uint64_t low() const {
// Our MD5 implementation returns the result in little endian, so the low
// word is first.
using namespace support;
return endian::read<uint64_t, little, unaligned>(Bytes.data());
}
uint64_t high() const {
using namespace support;
return endian::read<uint64_t, little, unaligned>(Bytes.data() + 8);
}
std::pair<uint64_t, uint64_t> words() const {
using namespace support;
return std::make_pair(high(), low());
}
};
MD5();
/// Updates the hash for the byte stream provided.
void update(ArrayRef<uint8_t> Data);
/// Updates the hash for the StringRef provided.
void update(StringRef Str);
/// Finishes off the hash and puts the result in result.
void final(MD5Result &Result);
/// Finishes off the hash, and returns a reference to the 16-byte hash data.
StringRef final();
/// Finishes off the hash, and returns a reference to the 16-byte hash data.
/// This is suitable for getting the MD5 at any time without invalidating the
/// internal state, so that more calls can be made into `update`.
StringRef result();
/// Translates the bytes in \p Res to a hex string that is
/// deposited into \p Str. The result will be of length 32.
static void stringifyResult(MD5Result &Result, SmallVectorImpl<char> &Str);
/// Computes the hash for a given bytes.
static std::array<uint8_t, 16> hash(ArrayRef<uint8_t> Data);
private:
// Any 32-bit or wider unsigned integer data type will do.
typedef uint32_t MD5_u32plus;
// Internal State
struct {
MD5_u32plus a = 0x67452301;
MD5_u32plus b = 0xefcdab89;
MD5_u32plus c = 0x98badcfe;
MD5_u32plus d = 0x10325476;
MD5_u32plus hi = 0;
MD5_u32plus lo = 0;
uint8_t buffer[64];
MD5_u32plus block[16];
} InternalState;
MD5Result Result;
const uint8_t *body(ArrayRef<uint8_t> Data);
};
inline bool operator==(const MD5::MD5Result &LHS, const MD5::MD5Result &RHS) {
return LHS.Bytes == RHS.Bytes;
}
/// Helper to compute and return lower 64 bits of the given string's MD5 hash.
inline uint64_t MD5Hash(StringRef Str) {
using namespace support;
MD5 Hash;
Hash.update(Str);
MD5::MD5Result Result;
Hash.final(Result);
// Return the least significant word.
return Result.low();
}
} // end namespace llvm
#endif // LLVM_SUPPORT_MD5_H
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
|