Annotation of embedaddon/rsync/lib/md5p8.c, revision 1.1.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>