1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/utils/SkMD5.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,252 @@ 1.4 +/* 1.5 + * Copyright 2012 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + * 1.10 + * The following code is based on the description in RFC 1321. 1.11 + * http://www.ietf.org/rfc/rfc1321.txt 1.12 + */ 1.13 + 1.14 +#include "SkTypes.h" 1.15 +#include "SkMD5.h" 1.16 +#include <string.h> 1.17 + 1.18 +/** MD5 basic transformation. Transforms state based on block. */ 1.19 +static void transform(uint32_t state[4], const uint8_t block[64]); 1.20 + 1.21 +/** Encodes input into output (4 little endian 32 bit values). */ 1.22 +static void encode(uint8_t output[16], const uint32_t input[4]); 1.23 + 1.24 +/** Encodes input into output (little endian 64 bit value). */ 1.25 +static void encode(uint8_t output[8], const uint64_t input); 1.26 + 1.27 +/** Decodes input (4 little endian 32 bit values) into storage, if required. */ 1.28 +static const uint32_t* decode(uint32_t storage[16], const uint8_t input[64]); 1.29 + 1.30 +SkMD5::SkMD5() : byteCount(0) { 1.31 + // These are magic numbers from the specification. 1.32 + this->state[0] = 0x67452301; 1.33 + this->state[1] = 0xefcdab89; 1.34 + this->state[2] = 0x98badcfe; 1.35 + this->state[3] = 0x10325476; 1.36 +} 1.37 + 1.38 +void SkMD5::update(const uint8_t* input, size_t inputLength) { 1.39 + unsigned int bufferIndex = (unsigned int)(this->byteCount & 0x3F); 1.40 + unsigned int bufferAvailable = 64 - bufferIndex; 1.41 + 1.42 + unsigned int inputIndex; 1.43 + if (inputLength >= bufferAvailable) { 1.44 + if (bufferIndex) { 1.45 + memcpy(&this->buffer[bufferIndex], input, bufferAvailable); 1.46 + transform(this->state, this->buffer); 1.47 + inputIndex = bufferAvailable; 1.48 + } else { 1.49 + inputIndex = 0; 1.50 + } 1.51 + 1.52 + for (; inputIndex + 63 < inputLength; inputIndex += 64) { 1.53 + transform(this->state, &input[inputIndex]); 1.54 + } 1.55 + 1.56 + bufferIndex = 0; 1.57 + } else { 1.58 + inputIndex = 0; 1.59 + } 1.60 + 1.61 + memcpy(&this->buffer[bufferIndex], &input[inputIndex], inputLength - inputIndex); 1.62 + 1.63 + this->byteCount += inputLength; 1.64 +} 1.65 + 1.66 +void SkMD5::finish(Digest& digest) { 1.67 + // Get the number of bits before padding. 1.68 + uint8_t bits[8]; 1.69 + encode(bits, this->byteCount << 3); 1.70 + 1.71 + // Pad out to 56 mod 64. 1.72 + unsigned int bufferIndex = (unsigned int)(this->byteCount & 0x3F); 1.73 + unsigned int paddingLength = (bufferIndex < 56) ? (56 - bufferIndex) : (120 - bufferIndex); 1.74 + static uint8_t PADDING[64] = { 1.75 + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.76 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.77 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.78 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.79 + }; 1.80 + this->update(PADDING, paddingLength); 1.81 + 1.82 + // Append length (length before padding, will cause final update). 1.83 + this->update(bits, 8); 1.84 + 1.85 + // Write out digest. 1.86 + encode(digest.data, this->state); 1.87 + 1.88 +#if defined(SK_MD5_CLEAR_DATA) 1.89 + // Clear state. 1.90 + memset(this, 0, sizeof(*this)); 1.91 +#endif 1.92 +} 1.93 + 1.94 +struct F { uint32_t operator()(uint32_t x, uint32_t y, uint32_t z) { 1.95 + //return (x & y) | ((~x) & z); 1.96 + return ((y ^ z) & x) ^ z; //equivelent but faster 1.97 +}}; 1.98 + 1.99 +struct G { uint32_t operator()(uint32_t x, uint32_t y, uint32_t z) { 1.100 + return (x & z) | (y & (~z)); 1.101 + //return ((x ^ y) & z) ^ y; //equivelent but slower 1.102 +}}; 1.103 + 1.104 +struct H { uint32_t operator()(uint32_t x, uint32_t y, uint32_t z) { 1.105 + return x ^ y ^ z; 1.106 +}}; 1.107 + 1.108 +struct I { uint32_t operator()(uint32_t x, uint32_t y, uint32_t z) { 1.109 + return y ^ (x | (~z)); 1.110 +}}; 1.111 + 1.112 +/** Rotates x left n bits. */ 1.113 +static inline uint32_t rotate_left(uint32_t x, uint8_t n) { 1.114 + return (x << n) | (x >> (32 - n)); 1.115 +} 1.116 + 1.117 +template <typename T> 1.118 +static inline void operation(T operation, uint32_t& a, uint32_t b, uint32_t c, uint32_t d, 1.119 + uint32_t x, uint8_t s, uint32_t t) { 1.120 + a = b + rotate_left(a + operation(b, c, d) + x + t, s); 1.121 +} 1.122 + 1.123 +static void transform(uint32_t state[4], const uint8_t block[64]) { 1.124 + uint32_t a = state[0], b = state[1], c = state[2], d = state[3]; 1.125 + 1.126 + uint32_t storage[16]; 1.127 + const uint32_t* X = decode(storage, block); 1.128 + 1.129 + // Round 1 1.130 + operation(F(), a, b, c, d, X[ 0], 7, 0xd76aa478); // 1 1.131 + operation(F(), d, a, b, c, X[ 1], 12, 0xe8c7b756); // 2 1.132 + operation(F(), c, d, a, b, X[ 2], 17, 0x242070db); // 3 1.133 + operation(F(), b, c, d, a, X[ 3], 22, 0xc1bdceee); // 4 1.134 + operation(F(), a, b, c, d, X[ 4], 7, 0xf57c0faf); // 5 1.135 + operation(F(), d, a, b, c, X[ 5], 12, 0x4787c62a); // 6 1.136 + operation(F(), c, d, a, b, X[ 6], 17, 0xa8304613); // 7 1.137 + operation(F(), b, c, d, a, X[ 7], 22, 0xfd469501); // 8 1.138 + operation(F(), a, b, c, d, X[ 8], 7, 0x698098d8); // 9 1.139 + operation(F(), d, a, b, c, X[ 9], 12, 0x8b44f7af); // 10 1.140 + operation(F(), c, d, a, b, X[10], 17, 0xffff5bb1); // 11 1.141 + operation(F(), b, c, d, a, X[11], 22, 0x895cd7be); // 12 1.142 + operation(F(), a, b, c, d, X[12], 7, 0x6b901122); // 13 1.143 + operation(F(), d, a, b, c, X[13], 12, 0xfd987193); // 14 1.144 + operation(F(), c, d, a, b, X[14], 17, 0xa679438e); // 15 1.145 + operation(F(), b, c, d, a, X[15], 22, 0x49b40821); // 16 1.146 + 1.147 + // Round 2 1.148 + operation(G(), a, b, c, d, X[ 1], 5, 0xf61e2562); // 17 1.149 + operation(G(), d, a, b, c, X[ 6], 9, 0xc040b340); // 18 1.150 + operation(G(), c, d, a, b, X[11], 14, 0x265e5a51); // 19 1.151 + operation(G(), b, c, d, a, X[ 0], 20, 0xe9b6c7aa); // 20 1.152 + operation(G(), a, b, c, d, X[ 5], 5, 0xd62f105d); // 21 1.153 + operation(G(), d, a, b, c, X[10], 9, 0x2441453); // 22 1.154 + operation(G(), c, d, a, b, X[15], 14, 0xd8a1e681); // 23 1.155 + operation(G(), b, c, d, a, X[ 4], 20, 0xe7d3fbc8); // 24 1.156 + operation(G(), a, b, c, d, X[ 9], 5, 0x21e1cde6); // 25 1.157 + operation(G(), d, a, b, c, X[14], 9, 0xc33707d6); // 26 1.158 + operation(G(), c, d, a, b, X[ 3], 14, 0xf4d50d87); // 27 1.159 + operation(G(), b, c, d, a, X[ 8], 20, 0x455a14ed); // 28 1.160 + operation(G(), a, b, c, d, X[13], 5, 0xa9e3e905); // 29 1.161 + operation(G(), d, a, b, c, X[ 2], 9, 0xfcefa3f8); // 30 1.162 + operation(G(), c, d, a, b, X[ 7], 14, 0x676f02d9); // 31 1.163 + operation(G(), b, c, d, a, X[12], 20, 0x8d2a4c8a); // 32 1.164 + 1.165 + // Round 3 1.166 + operation(H(), a, b, c, d, X[ 5], 4, 0xfffa3942); // 33 1.167 + operation(H(), d, a, b, c, X[ 8], 11, 0x8771f681); // 34 1.168 + operation(H(), c, d, a, b, X[11], 16, 0x6d9d6122); // 35 1.169 + operation(H(), b, c, d, a, X[14], 23, 0xfde5380c); // 36 1.170 + operation(H(), a, b, c, d, X[ 1], 4, 0xa4beea44); // 37 1.171 + operation(H(), d, a, b, c, X[ 4], 11, 0x4bdecfa9); // 38 1.172 + operation(H(), c, d, a, b, X[ 7], 16, 0xf6bb4b60); // 39 1.173 + operation(H(), b, c, d, a, X[10], 23, 0xbebfbc70); // 40 1.174 + operation(H(), a, b, c, d, X[13], 4, 0x289b7ec6); // 41 1.175 + operation(H(), d, a, b, c, X[ 0], 11, 0xeaa127fa); // 42 1.176 + operation(H(), c, d, a, b, X[ 3], 16, 0xd4ef3085); // 43 1.177 + operation(H(), b, c, d, a, X[ 6], 23, 0x4881d05); // 44 1.178 + operation(H(), a, b, c, d, X[ 9], 4, 0xd9d4d039); // 45 1.179 + operation(H(), d, a, b, c, X[12], 11, 0xe6db99e5); // 46 1.180 + operation(H(), c, d, a, b, X[15], 16, 0x1fa27cf8); // 47 1.181 + operation(H(), b, c, d, a, X[ 2], 23, 0xc4ac5665); // 48 1.182 + 1.183 + // Round 4 1.184 + operation(I(), a, b, c, d, X[ 0], 6, 0xf4292244); // 49 1.185 + operation(I(), d, a, b, c, X[ 7], 10, 0x432aff97); // 50 1.186 + operation(I(), c, d, a, b, X[14], 15, 0xab9423a7); // 51 1.187 + operation(I(), b, c, d, a, X[ 5], 21, 0xfc93a039); // 52 1.188 + operation(I(), a, b, c, d, X[12], 6, 0x655b59c3); // 53 1.189 + operation(I(), d, a, b, c, X[ 3], 10, 0x8f0ccc92); // 54 1.190 + operation(I(), c, d, a, b, X[10], 15, 0xffeff47d); // 55 1.191 + operation(I(), b, c, d, a, X[ 1], 21, 0x85845dd1); // 56 1.192 + operation(I(), a, b, c, d, X[ 8], 6, 0x6fa87e4f); // 57 1.193 + operation(I(), d, a, b, c, X[15], 10, 0xfe2ce6e0); // 58 1.194 + operation(I(), c, d, a, b, X[ 6], 15, 0xa3014314); // 59 1.195 + operation(I(), b, c, d, a, X[13], 21, 0x4e0811a1); // 60 1.196 + operation(I(), a, b, c, d, X[ 4], 6, 0xf7537e82); // 61 1.197 + operation(I(), d, a, b, c, X[11], 10, 0xbd3af235); // 62 1.198 + operation(I(), c, d, a, b, X[ 2], 15, 0x2ad7d2bb); // 63 1.199 + operation(I(), b, c, d, a, X[ 9], 21, 0xeb86d391); // 64 1.200 + 1.201 + state[0] += a; 1.202 + state[1] += b; 1.203 + state[2] += c; 1.204 + state[3] += d; 1.205 + 1.206 +#if defined(SK_MD5_CLEAR_DATA) 1.207 + // Clear sensitive information. 1.208 + if (X == &storage) { 1.209 + memset(storage, 0, sizeof(storage)); 1.210 + } 1.211 +#endif 1.212 +} 1.213 + 1.214 +static void encode(uint8_t output[16], const uint32_t input[4]) { 1.215 + for (size_t i = 0, j = 0; i < 4; i++, j += 4) { 1.216 + output[j ] = (uint8_t) (input[i] & 0xff); 1.217 + output[j+1] = (uint8_t)((input[i] >> 8) & 0xff); 1.218 + output[j+2] = (uint8_t)((input[i] >> 16) & 0xff); 1.219 + output[j+3] = (uint8_t)((input[i] >> 24) & 0xff); 1.220 + } 1.221 +} 1.222 + 1.223 +static void encode(uint8_t output[8], const uint64_t input) { 1.224 + output[0] = (uint8_t) (input & 0xff); 1.225 + output[1] = (uint8_t)((input >> 8) & 0xff); 1.226 + output[2] = (uint8_t)((input >> 16) & 0xff); 1.227 + output[3] = (uint8_t)((input >> 24) & 0xff); 1.228 + output[4] = (uint8_t)((input >> 32) & 0xff); 1.229 + output[5] = (uint8_t)((input >> 40) & 0xff); 1.230 + output[6] = (uint8_t)((input >> 48) & 0xff); 1.231 + output[7] = (uint8_t)((input >> 56) & 0xff); 1.232 +} 1.233 + 1.234 +static inline bool is_aligned(const void *pointer, size_t byte_count) { 1.235 + return reinterpret_cast<uintptr_t>(pointer) % byte_count == 0; 1.236 +} 1.237 + 1.238 +static const uint32_t* decode(uint32_t storage[16], const uint8_t input[64]) { 1.239 +#if defined(SK_CPU_LENDIAN) && defined(SK_CPU_FAST_UNALIGNED_ACCESS) 1.240 + return reinterpret_cast<const uint32_t*>(input); 1.241 +#else 1.242 +#if defined(SK_CPU_LENDIAN) 1.243 + if (is_aligned(input, 4)) { 1.244 + return reinterpret_cast<const uint32_t*>(input); 1.245 + } 1.246 +#endif 1.247 + for (size_t i = 0, j = 0; j < 64; i++, j += 4) { 1.248 + storage[i] = ((uint32_t)input[j ]) | 1.249 + (((uint32_t)input[j+1]) << 8) | 1.250 + (((uint32_t)input[j+2]) << 16) | 1.251 + (((uint32_t)input[j+3]) << 24); 1.252 + } 1.253 + return storage; 1.254 +#endif 1.255 +}