Annotation of embedaddon/rsync/checksum.c, revision 1.1.1.4

1.1       misho       1: /*
                      2:  * Routines to support checksumming of bytes.
                      3:  *
                      4:  * Copyright (C) 1996 Andrew Tridgell
                      5:  * Copyright (C) 1996 Paul Mackerras
1.1.1.4 ! misho       6:  * Copyright (C) 2004-2020 Wayne Davison
1.1       misho       7:  *
                      8:  * This program is free software; you can redistribute it and/or modify
                      9:  * it under the terms of the GNU General Public License as published by
                     10:  * the Free Software Foundation; either version 3 of the License, or
                     11:  * (at your option) any later version.
                     12:  *
1.1.1.4 ! misho      13:  * In addition, as a special exception, the copyright holders give
        !            14:  * permission to dynamically link rsync with the OpenSSL and xxhash
        !            15:  * libraries when those libraries are being distributed in compliance
        !            16:  * with their license terms, and to distribute a dynamically linked
        !            17:  * combination of rsync and these libraries.  This is also considered
        !            18:  * to be covered under the GPL's System Libraries exception.
        !            19:  *
1.1       misho      20:  * This program is distributed in the hope that it will be useful,
                     21:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     22:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     23:  * GNU General Public License for more details.
                     24:  *
                     25:  * You should have received a copy of the GNU General Public License along
                     26:  * with this program; if not, visit the http://fsf.org website.
                     27:  */
                     28: 
                     29: #include "rsync.h"
                     30: 
1.1.1.4 ! misho      31: #ifdef SUPPORT_XXHASH
        !            32: #include <xxhash.h>
        !            33: # if XXH_VERSION_NUMBER >= 800
        !            34: #  define SUPPORT_XXH3 1
        !            35: # endif
        !            36: #endif
        !            37: 
        !            38: extern int am_server;
        !            39: extern int whole_file;
1.1       misho      40: extern int checksum_seed;
                     41: extern int protocol_version;
1.1.1.3   misho      42: extern int proper_seed_order;
1.1.1.4 ! misho      43: extern int use_db;
        !            44: extern const char *checksum_choice;
        !            45: 
        !            46: struct name_num_obj valid_checksums = {
        !            47:        "checksum", NULL, NULL, 0, 0, {
        !            48: #ifdef SUPPORT_XXH3
        !            49:                { CSUM_XXH3_128, "xxh128", NULL },
        !            50:                { CSUM_XXH3_64, "xxh3", NULL },
        !            51: #endif
        !            52: #ifdef SUPPORT_XXHASH
        !            53:                { CSUM_XXH64, "xxh64", NULL },
        !            54:                { CSUM_XXH64, "xxhash", NULL },
        !            55: #endif
        !            56:                { CSUM_MD5P8, "md5p8", NULL },
        !            57:                { CSUM_MD5, "md5", NULL },
        !            58:                { CSUM_MD4, "md4", NULL },
        !            59:                { CSUM_NONE, "none", NULL },
        !            60:                { 0, NULL, NULL }
        !            61:        }
        !            62: };
        !            63: 
        !            64: int xfersum_type = 0; /* used for the file transfer checksums */
        !            65: int checksum_type = 0; /* used for the pre-transfer (--checksum) checksums */
        !            66: 
        !            67: int parse_csum_name(const char *name, int len)
        !            68: {
        !            69:        struct name_num_item *nni;
        !            70: 
        !            71:        if (len < 0 && name)
        !            72:                len = strlen(name);
        !            73: 
        !            74:        if (!name || (len == 4 && strncasecmp(name, "auto", 4) == 0)) {
        !            75:                if (protocol_version >= 30)
        !            76:                        return CSUM_MD5;
        !            77:                if (protocol_version >= 27)
        !            78:                        return CSUM_MD4_OLD;
        !            79:                if (protocol_version >= 21)
        !            80:                        return CSUM_MD4_BUSTED;
        !            81:                return CSUM_MD4_ARCHAIC;
        !            82:        }
        !            83: 
        !            84:        nni = get_nni_by_name(&valid_checksums, name, len);
        !            85: 
        !            86:        if (!nni) {
        !            87:                rprintf(FERROR, "unknown checksum name: %s\n", name);
        !            88:                exit_cleanup(RERR_UNSUPPORTED);
        !            89:        }
        !            90: 
        !            91:        return nni->num;
        !            92: }
        !            93: 
        !            94: static const char *checksum_name(int num)
        !            95: {
        !            96:        struct name_num_item *nni = get_nni_by_num(&valid_checksums, num);
        !            97: 
        !            98:        return nni ? nni->name : num < CSUM_MD4 ? "md4" : "UNKNOWN";
        !            99: }
        !           100: 
        !           101: void parse_checksum_choice(int final_call)
        !           102: {
        !           103:        if (valid_checksums.negotiated_name)
        !           104:                xfersum_type = checksum_type = valid_checksums.negotiated_num;
        !           105:        else {
        !           106:                char *cp = checksum_choice ? strchr(checksum_choice, ',') : NULL;
        !           107:                if (cp) {
        !           108:                        xfersum_type = parse_csum_name(checksum_choice, cp - checksum_choice);
        !           109:                        checksum_type = parse_csum_name(cp+1, -1);
        !           110:                } else
        !           111:                        xfersum_type = checksum_type = parse_csum_name(checksum_choice, -1);
        !           112:                if (am_server && checksum_choice)
        !           113:                        validate_choice_vs_env(NSTR_CHECKSUM, xfersum_type, checksum_type);
        !           114:        }
        !           115: 
        !           116:        if (xfersum_type == CSUM_NONE)
        !           117:                whole_file = 1;
1.1       misho     118: 
1.1.1.4 ! misho     119:        /* Snag the checksum name for both write_batch's option output & the following debug output. */
        !           120:        if (valid_checksums.negotiated_name)
        !           121:                checksum_choice = valid_checksums.negotiated_name;
        !           122:        else if (checksum_choice == NULL)
        !           123:                checksum_choice = checksum_name(xfersum_type);
        !           124: 
        !           125:        if (final_call && DEBUG_GTE(NSTR, am_server ? 3 : 1)) {
        !           126:                rprintf(FINFO, "%s%s checksum: %s\n",
        !           127:                        am_server ? "Server" : "Client",
        !           128:                        valid_checksums.negotiated_name ? " negotiated" : "",
        !           129:                        checksum_choice);
        !           130:        }
        !           131: }
        !           132: 
        !           133: int csum_len_for_type(int cst, BOOL flist_csum)
        !           134: {
        !           135:        switch (cst) {
        !           136:          case CSUM_NONE:
        !           137:                return 1;
        !           138:          case CSUM_MD4_ARCHAIC:
        !           139:                /* The oldest checksum code is rather weird: the file-list code only sent
        !           140:                 * 2-byte checksums, but all other checksums were full MD4 length. */
        !           141:                return flist_csum ? 2 : MD4_DIGEST_LEN;
        !           142:          case CSUM_MD4:
        !           143:          case CSUM_MD4_OLD:
        !           144:          case CSUM_MD4_BUSTED:
        !           145:                return MD4_DIGEST_LEN;
        !           146:          case CSUM_MD5P8:
        !           147:          case CSUM_MD5:
        !           148:                return MD5_DIGEST_LEN;
        !           149:          case CSUM_XXH64:
        !           150:          case CSUM_XXH3_64:
        !           151:                return 64/8;
        !           152:          case CSUM_XXH3_128:
        !           153:                return 128/8;
        !           154:          default: /* paranoia to prevent missing case values */
        !           155:                exit_cleanup(RERR_UNSUPPORTED);
        !           156:        }
        !           157:        return 0;
        !           158: }
        !           159: 
        !           160: /* Returns 0 if the checksum is not canonical (i.e. it includes a seed value).
        !           161:  * Returns 1 if the public sum order matches our internal sum order.
        !           162:  * Returns -1 if the public sum order is the reverse of our internal sum order.
        !           163:  */
        !           164: int canonical_checksum(int csum_type)
        !           165: {
        !           166:        switch (csum_type) {
        !           167:          case CSUM_NONE:
        !           168:          case CSUM_MD4_ARCHAIC:
        !           169:          case CSUM_MD4_OLD:
        !           170:          case CSUM_MD4_BUSTED:
        !           171:                break;
        !           172:          case CSUM_MD4:
        !           173:          case CSUM_MD5P8:
        !           174:          case CSUM_MD5:
        !           175:                return -1;
        !           176:          case CSUM_XXH64:
        !           177:          case CSUM_XXH3_64:
        !           178:          case CSUM_XXH3_128:
        !           179:                return 1;
        !           180:          default: /* paranoia to prevent missing case values */
        !           181:                exit_cleanup(RERR_UNSUPPORTED);
        !           182:        }
        !           183:        return 0;
        !           184: }
        !           185: 
        !           186: #ifdef HAVE_SIMD /* See simd-checksum-*.cpp. */
        !           187: #define get_checksum2 get_checksum2_nosimd
        !           188: #else
1.1       misho     189: /*
1.1.1.4 ! misho     190:   a simple 32 bit checksum that can be updated from either end
1.1       misho     191:   (inspired by Mark Adler's Adler-32 checksum)
                    192:   */
                    193: uint32 get_checksum1(char *buf1, int32 len)
                    194: {
1.1.1.4 ! misho     195:        int32 i;
        !           196:        uint32 s1, s2;
        !           197:        schar *buf = (schar *)buf1;
        !           198: 
        !           199:        s1 = s2 = 0;
        !           200:        for (i = 0; i < (len-4); i+=4) {
        !           201:                s2 += 4*(s1 + buf[i]) + 3*buf[i+1] + 2*buf[i+2] + buf[i+3] + 10*CHAR_OFFSET;
        !           202:                s1 += (buf[i+0] + buf[i+1] + buf[i+2] + buf[i+3] + 4*CHAR_OFFSET);
        !           203:        }
        !           204:        for (; i < len; i++) {
        !           205:                s1 += (buf[i]+CHAR_OFFSET); s2 += s1;
        !           206:        }
        !           207:        return (s1 & 0xffff) + (s2 << 16);
1.1       misho     208: }
                    209: 
1.1.1.4 ! misho     210: void checksum2_enable_prefetch(UNUSED(struct map_struct *map), UNUSED(OFF_T len), UNUSED(int32 blocklen))
        !           211: {
        !           212: }
1.1       misho     213: 
1.1.1.4 ! misho     214: void checksum2_disable_prefetch()
1.1       misho     215: {
1.1.1.4 ! misho     216: }
        !           217: #endif
1.1       misho     218: 
1.1.1.4 ! misho     219: /* Renamed to get_checksum2_nosimd() with HAVE_SIMD */
        !           220: void get_checksum2(char *buf, int32 len, char *sum, UNUSED(OFF_T prefetch_offset))
        !           221: {
        !           222:        switch (xfersum_type) {
        !           223: #ifdef SUPPORT_XXHASH
        !           224:          case CSUM_XXH64:
        !           225:                SIVAL64(sum, 0, XXH64(buf, len, checksum_seed));
        !           226:                break;
        !           227: #endif
        !           228: #ifdef SUPPORT_XXH3
        !           229:          case CSUM_XXH3_64:
        !           230:                SIVAL64(sum, 0, XXH3_64bits_withSeed(buf, len, checksum_seed));
        !           231:                break;
        !           232:          case CSUM_XXH3_128: {
        !           233:                XXH128_hash_t digest = XXH3_128bits_withSeed(buf, len, checksum_seed);
        !           234:                SIVAL64(sum, 0, digest.low64);
        !           235:                SIVAL64(sum, 8, digest.high64);
        !           236:                break;
        !           237:          }
        !           238: #endif
        !           239:          case CSUM_MD5P8:  /* == CSUM_MD5 for checksum2 */
        !           240:          case CSUM_MD5: {
        !           241:                MD5_CTX m5;
1.1       misho     242:                uchar seedbuf[4];
1.1.1.4 ! misho     243:                MD5_Init(&m5);
1.1.1.3   misho     244:                if (proper_seed_order) {
                    245:                        if (checksum_seed) {
                    246:                                SIVALu(seedbuf, 0, checksum_seed);
1.1.1.4 ! misho     247:                                MD5_Update(&m5, seedbuf, 4);
1.1.1.3   misho     248:                        }
1.1.1.4 ! misho     249:                        MD5_Update(&m5, (uchar *)buf, len);
1.1.1.3   misho     250:                } else {
1.1.1.4 ! misho     251:                        MD5_Update(&m5, (uchar *)buf, len);
1.1.1.3   misho     252:                        if (checksum_seed) {
                    253:                                SIVALu(seedbuf, 0, checksum_seed);
1.1.1.4 ! misho     254:                                MD5_Update(&m5, seedbuf, 4);
1.1.1.3   misho     255:                        }
1.1       misho     256:                }
1.1.1.4 ! misho     257:                MD5_Final((uchar *)sum, &m5);
        !           258:                break;
        !           259:          }
        !           260:          case CSUM_MD4:
        !           261: #ifdef USE_OPENSSL
        !           262:          {
        !           263:                MD4_CTX m4;
        !           264:                MD4_Init(&m4);
        !           265:                MD4_Update(&m4, (uchar *)buf, len);
        !           266:                if (checksum_seed) {
        !           267:                        uchar seedbuf[4];
        !           268:                        SIVALu(seedbuf, 0, checksum_seed);
        !           269:                        MD4_Update(&m4, seedbuf, 4);
        !           270:                }
        !           271:                MD4_Final((uchar *)sum, &m4);
        !           272:                break;
        !           273:          }
        !           274: #endif
        !           275:          case CSUM_MD4_OLD:
        !           276:          case CSUM_MD4_BUSTED:
        !           277:          case CSUM_MD4_ARCHAIC: {
        !           278:                md_context m;
1.1       misho     279:                int32 i;
                    280:                static char *buf1;
                    281:                static int32 len1;
                    282: 
                    283:                mdfour_begin(&m);
                    284: 
                    285:                if (len > len1) {
                    286:                        if (buf1)
                    287:                                free(buf1);
                    288:                        buf1 = new_array(char, len+4);
                    289:                        len1 = len;
                    290:                }
                    291: 
                    292:                memcpy(buf1, buf, len);
                    293:                if (checksum_seed) {
                    294:                        SIVAL(buf1,len,checksum_seed);
                    295:                        len += 4;
                    296:                }
                    297: 
                    298:                for (i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK)
                    299:                        mdfour_update(&m, (uchar *)(buf1+i), CSUM_CHUNK);
                    300: 
                    301:                /*
                    302:                 * Prior to version 27 an incorrect MD4 checksum was computed
                    303:                 * by failing to call mdfour_tail() for block sizes that
                    304:                 * are multiples of 64.  This is fixed by calling mdfour_update()
                    305:                 * even when there are no more bytes.
                    306:                 */
1.1.1.4 ! misho     307:                if (len - i > 0 || xfersum_type > CSUM_MD4_BUSTED)
1.1       misho     308:                        mdfour_update(&m, (uchar *)(buf1+i), len-i);
                    309: 
                    310:                mdfour_result(&m, (uchar *)sum);
1.1.1.4 ! misho     311:                break;
        !           312:          }
        !           313:          default: /* paranoia to prevent missing case values */
        !           314:                exit_cleanup(RERR_UNSUPPORTED);
1.1       misho     315:        }
                    316: }
                    317: 
1.1.1.3   misho     318: void file_checksum(const char *fname, const STRUCT_STAT *st_p, char *sum)
1.1       misho     319: {
                    320:        struct map_struct *buf;
1.1.1.3   misho     321:        OFF_T i, len = st_p->st_size;
1.1       misho     322:        int32 remainder;
                    323:        int fd;
                    324: 
                    325:        memset(sum, 0, MAX_DIGEST_LEN);
                    326: 
                    327:        fd = do_open(fname, O_RDONLY, 0);
                    328:        if (fd == -1)
                    329:                return;
                    330: 
1.1.1.4 ! misho     331:        buf = map_file(fd, len, MAX_MAP_SIZE, CHUNK_SIZE);
1.1       misho     332: 
1.1.1.4 ! misho     333:        switch (checksum_type) {
        !           334: #ifdef SUPPORT_XXHASH
        !           335:          case CSUM_XXH64: {
        !           336:                static XXH64_state_t* state = NULL;
        !           337:                if (!state && !(state = XXH64_createState()))
        !           338:                        out_of_memory("file_checksum");
1.1       misho     339: 
1.1.1.4 ! misho     340:                XXH64_reset(state, 0);
        !           341: 
        !           342:                for (i = 0; i + CHUNK_SIZE <= len; i += CHUNK_SIZE)
        !           343:                        XXH64_update(state, (uchar *)map_ptr(buf, i, CHUNK_SIZE), CHUNK_SIZE);
        !           344: 
        !           345:                remainder = (int32)(len - i);
        !           346:                if (remainder > 0)
        !           347:                        XXH64_update(state, (uchar *)map_ptr(buf, i, remainder), remainder);
        !           348: 
        !           349:                SIVAL64(sum, 0, XXH64_digest(state));
        !           350:                break;
        !           351:          }
        !           352: #endif
        !           353: #ifdef SUPPORT_XXH3
        !           354:          case CSUM_XXH3_64: {
        !           355:                static XXH3_state_t* state = NULL;
        !           356:                if (!state && !(state = XXH3_createState()))
        !           357:                        out_of_memory("file_checksum");
        !           358: 
        !           359:                XXH3_64bits_reset(state);
        !           360: 
        !           361:                for (i = 0; i + CHUNK_SIZE <= len; i += CHUNK_SIZE)
        !           362:                        XXH3_64bits_update(state, (uchar *)map_ptr(buf, i, CHUNK_SIZE), CHUNK_SIZE);
        !           363: 
        !           364:                remainder = (int32)(len - i);
        !           365:                if (remainder > 0)
        !           366:                        XXH3_64bits_update(state, (uchar *)map_ptr(buf, i, remainder), remainder);
        !           367: 
        !           368:                SIVAL64(sum, 0, XXH3_64bits_digest(state));
        !           369:                break;
        !           370:          }
        !           371:          case CSUM_XXH3_128: {
        !           372:                XXH128_hash_t digest;
        !           373:                static XXH3_state_t* state = NULL;
        !           374:                if (!state && !(state = XXH3_createState()))
        !           375:                        out_of_memory("file_checksum");
        !           376: 
        !           377:                XXH3_128bits_reset(state);
        !           378: 
        !           379:                for (i = 0; i + CHUNK_SIZE <= len; i += CHUNK_SIZE)
        !           380:                        XXH3_128bits_update(state, (uchar *)map_ptr(buf, i, CHUNK_SIZE), CHUNK_SIZE);
        !           381: 
        !           382:                remainder = (int32)(len - i);
        !           383:                if (remainder > 0)
        !           384:                        XXH3_128bits_update(state, (uchar *)map_ptr(buf, i, remainder), remainder);
        !           385: 
        !           386:                digest = XXH3_128bits_digest(state);
        !           387:                SIVAL64(sum, 0, digest.low64);
        !           388:                SIVAL64(sum, 8, digest.high64);
        !           389:                break;
        !           390:          }
        !           391: #endif
        !           392:          case CSUM_MD5P8: {
        !           393:                MD5P8_CTX m5p8;
        !           394: 
        !           395:                MD5P8_Init(&m5p8);
        !           396: 
        !           397:                for (i = 0; i + CHUNK_SIZE <= len; i += CHUNK_SIZE)
        !           398:                        MD5P8_Update(&m5p8, (uchar *)map_ptr(buf, i, CHUNK_SIZE), CHUNK_SIZE);
1.1       misho     399: 
                    400:                remainder = (int32)(len - i);
                    401:                if (remainder > 0)
1.1.1.4 ! misho     402:                        MD5P8_Update(&m5p8, (uchar *)map_ptr(buf, i, remainder), remainder);
        !           403: 
        !           404:                MD5P8_Final((uchar *)sum, &m5p8);
        !           405:                break;
        !           406:          }
        !           407:          case CSUM_MD5: {
        !           408:                MD5_CTX m5;
        !           409: 
        !           410:                MD5_Init(&m5);
        !           411: 
        !           412:                for (i = 0; i + CHUNK_SIZE <= len; i += CHUNK_SIZE)
        !           413:                        MD5_Update(&m5, (uchar *)map_ptr(buf, i, CHUNK_SIZE), CHUNK_SIZE);
        !           414: 
        !           415:                remainder = (int32)(len - i);
        !           416:                if (remainder > 0)
        !           417:                        MD5_Update(&m5, (uchar *)map_ptr(buf, i, remainder), remainder);
        !           418: 
        !           419:                MD5_Final((uchar *)sum, &m5);
        !           420:                if (use_db)
        !           421:                        db_set_checksum(5, st_p, sum);
        !           422:                break;
        !           423:          }
        !           424:          case CSUM_MD4:
        !           425: #ifdef USE_OPENSSL
        !           426:          {
        !           427:                MD4_CTX m4;
        !           428: 
        !           429:                MD4_Init(&m4);
        !           430: 
        !           431:                for (i = 0; i + CHUNK_SIZE <= len; i += CHUNK_SIZE)
        !           432:                        MD4_Update(&m4, (uchar *)map_ptr(buf, i, CHUNK_SIZE), CHUNK_SIZE);
        !           433: 
        !           434:                remainder = (int32)(len - i);
        !           435:                if (remainder > 0)
        !           436:                        MD4_Update(&m4, (uchar *)map_ptr(buf, i, remainder), remainder);
        !           437: 
        !           438:                MD4_Final((uchar *)sum, &m4);
        !           439:                break;
        !           440:          }
        !           441: #endif
        !           442:          case CSUM_MD4_OLD:
        !           443:          case CSUM_MD4_BUSTED:
        !           444:          case CSUM_MD4_ARCHAIC: {
        !           445:                md_context m;
1.1       misho     446: 
                    447:                mdfour_begin(&m);
                    448: 
1.1.1.4 ! misho     449:                for (i = 0; i + CHUNK_SIZE <= len; i += CHUNK_SIZE)
        !           450:                        mdfour_update(&m, (uchar *)map_ptr(buf, i, CHUNK_SIZE), CHUNK_SIZE);
1.1       misho     451: 
                    452:                /* Prior to version 27 an incorrect MD4 checksum was computed
                    453:                 * by failing to call mdfour_tail() for block sizes that
                    454:                 * are multiples of 64.  This is fixed by calling mdfour_update()
                    455:                 * even when there are no more bytes. */
                    456:                remainder = (int32)(len - i);
1.1.1.4 ! misho     457:                if (remainder > 0 || checksum_type > CSUM_MD4_BUSTED)
1.1       misho     458:                        mdfour_update(&m, (uchar *)map_ptr(buf, i, remainder), remainder);
                    459: 
                    460:                mdfour_result(&m, (uchar *)sum);
1.1.1.4 ! misho     461:                if (use_db)
        !           462:                        db_set_checksum(4, st_p, sum);
        !           463:                break;
        !           464:          }
        !           465:          default:
        !           466:                rprintf(FERROR, "Invalid checksum-choice for --checksum: %s (%d)\n",
        !           467:                        checksum_name(checksum_type), checksum_type);
        !           468:                exit_cleanup(RERR_UNSUPPORTED);
1.1       misho     469:        }
                    470: 
                    471:        close(fd);
                    472:        unmap_file(buf);
                    473: }
                    474: 
                    475: static int32 sumresidue;
1.1.1.4 ! misho     476: static union {
        !           477:        md_context md;
        !           478: #ifdef USE_OPENSSL
        !           479:        MD4_CTX m4;
        !           480: #endif
        !           481:        MD5_CTX m5;
        !           482: } ctx, ctx2;
        !           483: #ifdef SUPPORT_XXHASH
        !           484: static XXH64_state_t* xxh64_state;
        !           485: #endif
        !           486: #ifdef SUPPORT_XXH3
        !           487: static XXH3_state_t* xxh3_state;
        !           488: #endif
        !           489: static int cursum_type;
1.1       misho     490: 
1.1.1.4 ! misho     491: void sum_init(int csum_type, int seed)
1.1       misho     492: {
                    493:        char s[4];
                    494: 
1.1.1.4 ! misho     495:        if (csum_type < 0)
        !           496:                csum_type = parse_csum_name(NULL, 0);
        !           497:        cursum_type = csum_type;
        !           498: 
        !           499:        switch (csum_type) {
        !           500: #ifdef SUPPORT_XXHASH
        !           501:          case CSUM_XXH64:
        !           502:                if (!xxh64_state && !(xxh64_state = XXH64_createState()))
        !           503:                        out_of_memory("sum_init");
        !           504:                XXH64_reset(xxh64_state, 0);
        !           505:                break;
        !           506: #endif
        !           507: #ifdef SUPPORT_XXH3
        !           508:          case CSUM_XXH3_64:
        !           509:                if (!xxh3_state && !(xxh3_state = XXH3_createState()))
        !           510:                        out_of_memory("sum_init");
        !           511:                XXH3_64bits_reset(xxh3_state);
        !           512:                break;
        !           513:          case CSUM_XXH3_128:
        !           514:                if (!xxh3_state && !(xxh3_state = XXH3_createState()))
        !           515:                        out_of_memory("sum_init");
        !           516:                XXH3_128bits_reset(xxh3_state);
        !           517:                break;
        !           518: #endif
        !           519:          case CSUM_MD5P8:
        !           520:                MD5P8_Init(&m5p8);
        !           521:                break;
        !           522:          case CSUM_MD5:
        !           523:                MD5_Init(&ctx.m5);
        !           524:                if (link_by_hash_dir)
        !           525:                        MD5_Init(&ctx2.m5);
        !           526:                break;
        !           527:          case CSUM_MD4:
        !           528: #ifdef USE_OPENSSL
        !           529:                MD4_Init(&ctx.m4);
        !           530: #else
        !           531:                mdfour_begin(&ctx.md);
        !           532:                sumresidue = 0;
        !           533: #endif
        !           534:                break;
        !           535:          case CSUM_MD4_OLD:
        !           536:          case CSUM_MD4_BUSTED:
        !           537:          case CSUM_MD4_ARCHAIC:
        !           538:                mdfour_begin(&ctx.md);
1.1       misho     539:                sumresidue = 0;
                    540:                SIVAL(s, 0, seed);
                    541:                sum_update(s, 4);
1.1.1.4 ! misho     542:                break;
        !           543:          case CSUM_NONE:
        !           544:                break;
        !           545:          default: /* paranoia to prevent missing case values */
        !           546:                exit_cleanup(RERR_UNSUPPORTED);
1.1       misho     547:        }
                    548: }
                    549: 
                    550: /**
                    551:  * Feed data into an MD4 accumulator, md.  The results may be
                    552:  * retrieved using sum_end().  md is used for different purposes at
                    553:  * different points during execution.
                    554:  *
                    555:  * @todo Perhaps get rid of md and just pass in the address each time.
                    556:  * Very slightly clearer and slower.
                    557:  **/
                    558: void sum_update(const char *p, int32 len)
                    559: {
1.1.1.4 ! misho     560:        switch (cursum_type) {
        !           561: #ifdef SUPPORT_XXHASH
        !           562:          case CSUM_XXH64:
        !           563:                XXH64_update(xxh64_state, p, len);
        !           564:                break;
        !           565: #endif
        !           566: #ifdef SUPPORT_XXH3
        !           567:          case CSUM_XXH3_64:
        !           568:                XXH3_64bits_update(xxh3_state, p, len);
        !           569:                break;
        !           570:          case CSUM_XXH3_128:
        !           571:                XXH3_128bits_update(xxh3_state, p, len);
        !           572:                break;
        !           573: #endif
        !           574:          case CSUM_MD5P8:
        !           575:                MD5P8_Update(&m5p8, (uchar *)p, len);
        !           576:                break;
        !           577:          case CSUM_MD5:
        !           578:                MD5_Update(&ctx.m5, (uchar *)p, len);
        !           579:                if (link_by_hash_dir)
        !           580:                        MD5_Update(&ctx2.m5, (uchar *)p, len);
        !           581:                break;
        !           582:          case CSUM_MD4:
        !           583: #ifdef USE_OPENSSL
        !           584:                MD4_Update(&ctx.m4, (uchar *)p, len);
        !           585:                break;
        !           586: #endif
        !           587:          case CSUM_MD4_OLD:
        !           588:          case CSUM_MD4_BUSTED:
        !           589:          case CSUM_MD4_ARCHAIC:
        !           590:                if (len + sumresidue < CSUM_CHUNK) {
        !           591:                        memcpy(ctx.md.buffer + sumresidue, p, len);
        !           592:                        sumresidue += len;
        !           593:                        break;
        !           594:                }
1.1       misho     595: 
1.1.1.4 ! misho     596:                if (sumresidue) {
        !           597:                        int32 i = CSUM_CHUNK - sumresidue;
        !           598:                        memcpy(ctx.md.buffer + sumresidue, p, i);
        !           599:                        mdfour_update(&ctx.md, (uchar *)ctx.md.buffer, CSUM_CHUNK);
        !           600:                        len -= i;
        !           601:                        p += i;
        !           602:                }
1.1       misho     603: 
1.1.1.4 ! misho     604:                while (len >= CSUM_CHUNK) {
        !           605:                        mdfour_update(&ctx.md, (uchar *)p, CSUM_CHUNK);
        !           606:                        len -= CSUM_CHUNK;
        !           607:                        p += CSUM_CHUNK;
        !           608:                }
        !           609: 
        !           610:                sumresidue = len;
        !           611:                if (sumresidue)
        !           612:                        memcpy(ctx.md.buffer, p, sumresidue);
        !           613:                break;
        !           614:          case CSUM_NONE:
        !           615:                break;
        !           616:          default: /* paranoia to prevent missing case values */
        !           617:                exit_cleanup(RERR_UNSUPPORTED);
        !           618:        }
1.1       misho     619: }
                    620: 
1.1.1.4 ! misho     621: /* NOTE: all the callers of sum_end() pass in a pointer to a buffer that is
        !           622:  * MAX_DIGEST_LEN in size, so even if the csum-len is shorter that that (i.e.
        !           623:  * CSUM_MD4_ARCHAIC), we don't have to worry about limiting the data we write
        !           624:  * into the "sum" buffer. */
1.1       misho     625: int sum_end(char *sum)
                    626: {
1.1.1.4 ! misho     627:        switch (cursum_type) {
        !           628: #ifdef SUPPORT_XXHASH
        !           629:          case CSUM_XXH64:
        !           630:                SIVAL64(sum, 0, XXH64_digest(xxh64_state));
        !           631:                break;
        !           632: #endif
        !           633: #ifdef SUPPORT_XXH3
        !           634:          case CSUM_XXH3_64:
        !           635:                SIVAL64(sum, 0, XXH3_64bits_digest(xxh3_state));
        !           636:                break;
        !           637:          case CSUM_XXH3_128: {
        !           638:                XXH128_hash_t digest = XXH3_128bits_digest(xxh3_state);
        !           639:                SIVAL64(sum, 0, digest.low64);
        !           640:                SIVAL64(sum, 8, digest.high64);
        !           641:                break;
        !           642:          }
        !           643: #endif
        !           644:          case CSUM_MD5P8:
        !           645:                MD5P8_Final((uchar *)sum, &m5p8);
        !           646:                break;
        !           647:          case CSUM_MD5:
        !           648:                MD5_Final((uchar *)sum, &ctx.m5);
        !           649:                if (link_by_hash_dir)
        !           650:                        MD5_Final((uchar *)link_by_hash_extra_sum, &ctx2.m5);
        !           651:                break;
        !           652:          case CSUM_MD4:
        !           653: #ifdef USE_OPENSSL
        !           654:                MD4_Final((uchar *)sum, &ctx.m4);
        !           655:                break;
        !           656: #endif
        !           657:          case CSUM_MD4_OLD:
        !           658:                mdfour_update(&ctx.md, (uchar *)ctx.md.buffer, sumresidue);
        !           659:                mdfour_result(&ctx.md, (uchar *)sum);
        !           660:                break;
        !           661:          case CSUM_MD4_BUSTED:
        !           662:          case CSUM_MD4_ARCHAIC:
        !           663:                if (sumresidue)
        !           664:                        mdfour_update(&ctx.md, (uchar *)ctx.md.buffer, sumresidue);
        !           665:                mdfour_result(&ctx.md, (uchar *)sum);
        !           666:                break;
        !           667:          case CSUM_NONE:
        !           668:                *sum = '\0';
        !           669:                break;
        !           670:          default: /* paranoia to prevent missing case values */
        !           671:                exit_cleanup(RERR_UNSUPPORTED);
1.1       misho     672:        }
                    673: 
1.1.1.4 ! misho     674:        return csum_len_for_type(cursum_type, 0);
1.1       misho     675: }

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