Annotation of embedaddon/rsync/lib/md5p8.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * MD5-based hash friendly to parallel processing, reference implementation
        !             3:  *
        !             4:  * Author: Jorrit Jongma, 2020
        !             5:  *
        !             6:  * Released in the public domain falling back to the MIT license
        !             7:  * ( http://www.opensource.org/licenses/MIT ) in case public domain does not
        !             8:  * apply in your country.
        !             9:  */
        !            10: /*
        !            11:  * MD5P8 is an MD5-based hash friendly to parallel processing. The input
        !            12:  * stream is divided into 8 independent streams. For each 512 bytes of input,
        !            13:  * the first 64 bytes are send to the first stream, the second 64 bytes to
        !            14:  * the second stream, etc. The input stream is padded with zeros to the next
        !            15:  * multiple of 512 bytes, then a normal MD5 hash is computed on a buffer
        !            16:  * containing the A, B, C, and D states of the 8 individual streams, followed
        !            17:  * by the (unpadded) length of the input.
        !            18:  *
        !            19:  * On non-SIMD accelerated CPUs the performance of MD5P8 is slightly lower
        !            20:  * than normal MD5 (particularly on files smaller than 10 kB), but with
        !            21:  * SIMD-based parallel processing it can be two to six times as fast. Even in
        !            22:  * the best-case scenario, xxHash is still at least twice as fast and should
        !            23:  * be preferred when available.
        !            24:  */
        !            25: 
        !            26: #include "rsync.h"
        !            27: 
        !            28: #ifdef HAVE_SIMD
        !            29: #define MD5P8_Init MD5P8_Init_c
        !            30: #define MD5P8_Update MD5P8_Update_c
        !            31: #define MD5P8_Final MD5P8_Final_c
        !            32: #endif
        !            33: 
        !            34: /* each MD5_CTX needs to be 8-byte aligned */
        !            35: #define MD5P8_Contexts_c(ctx, index) ((MD5_CTX*)((((uintptr_t)((ctx)->context_storage) + 7) & ~7) + (index)*((sizeof(MD5_CTX) + 7) & ~7)))
        !            36: 
        !            37: void MD5P8_Init(MD5P8_CTX *ctx)
        !            38: {
        !            39:     int i;
        !            40:     for (i = 0; i < 8; i++) {
        !            41:         MD5_Init(MD5P8_Contexts_c(ctx, i));
        !            42:     }
        !            43:     ctx->used = 0;
        !            44:     ctx->next = 0;
        !            45: }
        !            46: 
        !            47: void MD5P8_Update(MD5P8_CTX *ctx, const uchar *input, uint32 length)
        !            48: {
        !            49:     uint32 pos = 0;
        !            50: 
        !            51:     if ((ctx->used) || (length < 64)) {
        !            52:         int cpy = MIN(length, 64 - ctx->used);
        !            53:         memmove(&ctx->buffer[ctx->used], input, cpy);
        !            54:         ctx->used += cpy;
        !            55:         length -= cpy;
        !            56:         pos += cpy;
        !            57: 
        !            58:         if (ctx->used == 64) {
        !            59:             MD5_Update(MD5P8_Contexts_c(ctx, ctx->next), ctx->buffer, 64);
        !            60:             ctx->used = 0;
        !            61:             ctx->next = (ctx->next + 1) % 8;
        !            62:         }
        !            63:     }
        !            64: 
        !            65:     while (length >= 64) {
        !            66:         MD5_Update(MD5P8_Contexts_c(ctx, ctx->next), &input[pos], 64);
        !            67:         ctx->next = (ctx->next + 1) % 8;
        !            68:         pos += 64;
        !            69:         length -= 64;
        !            70:     }
        !            71: 
        !            72:     if (length) {
        !            73:         memcpy(ctx->buffer, &input[pos], length);
        !            74:         ctx->used = length;
        !            75:     }
        !            76: }
        !            77: 
        !            78: void MD5P8_Final(uchar digest[MD5_DIGEST_LEN], MD5P8_CTX *ctx)
        !            79: {
        !            80:     int i;
        !            81:     uint32 low = 0, high = 0, sub = ctx->used ? 64 - ctx->used : 0;
        !            82:     if (ctx->used) {
        !            83:         uchar tmp[64];
        !            84:         memset(tmp, 0, 64);
        !            85:         MD5P8_Update(ctx, tmp, 64 - ctx->used);
        !            86:     }
        !            87:     memset(ctx->buffer, 0, 64);
        !            88:     while (ctx->next != 0) {
        !            89:         MD5P8_Update(ctx, ctx->buffer, 64);
        !            90:         sub += 64;
        !            91:     }
        !            92: 
        !            93:     uchar state[34*4] = {0};
        !            94: 
        !            95:     for (i = 0; i < 8; i++) {
        !            96:         MD5_CTX* md = MD5P8_Contexts_c(ctx, i);
        !            97: #ifdef USE_OPENSSL
        !            98:         if (low + md->Nl < low) high++;
        !            99:         low += md->Nl;
        !           100:         high += md->Nh;
        !           101: #else
        !           102:         if (low + md->totalN < low) high++;
        !           103:         low += md->totalN;
        !           104:         high += md->totalN2;
        !           105: #endif
        !           106:         SIVALu(state, i*16, md->A);
        !           107:         SIVALu(state, i*16 + 4, md->B);
        !           108:         SIVALu(state, i*16 + 8, md->C);
        !           109:         SIVALu(state, i*16 + 12, md->D);
        !           110:     }
        !           111: 
        !           112: #ifndef USE_OPENSSL
        !           113:        high = (low >> 29) | (high << 3);
        !           114:        low = (low << 3);
        !           115: #endif
        !           116: 
        !           117:     sub <<= 3;
        !           118:     if (low - sub > low) high--;
        !           119:     low -= sub;
        !           120: 
        !           121:     SIVALu(state, 32*4, low);
        !           122:     SIVALu(state, 33*4, high);
        !           123: 
        !           124:     MD5_CTX md;
        !           125:     MD5_Init(&md);
        !           126:     MD5_Update(&md, state, 34*4);
        !           127:     MD5_Final(digest, &md);
        !           128: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>