gfx/skia/trunk/src/utils/SkMD5.cpp

changeset 0
6474c204b198
     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 +}

mercurial