/* Process the remaining bytes in the buffer and put result from CTX * in first 16 bytes following RESBUF. The result is always in little * endian byte order, so that a byte-wise output yields to the wanted * ASCII representation of the message digest. * * IMPORTANT: On some systems it is required that RESBUF is correctly * aligned for a 32 bits value. */ void* FAST_FUNC md5_end(void *resbuf, md5_ctx_t *ctx) { char *buf = ctx->buffer; int i; /* Pad data to block size. */ buf[ctx->buflen++] = 0x80; memset(buf + ctx->buflen, 0, 128 - ctx->buflen); /* Put the 64-bit file length in *bits* at the end of the buffer. */ ctx->total <<= 3; if (ctx->buflen > 56) buf += 64; for (i = 0; i < 8; i++) buf[56 + i] = ctx->total >> (i*8); /* Process last bytes. */ if (buf != ctx->buffer) md5_hash_block(ctx->buffer, ctx); md5_hash_block(buf, ctx); /* Put result from CTX in first 16 bytes following RESBUF. The result is * always in little endian byte order, so that a byte-wise output yields * to the wanted ASCII representation of the message digest. * * IMPORTANT: On some systems it is required that RESBUF is correctly * aligned for a 32 bits value. */ ((uint32_t *) resbuf)[0] = SWAP_LE32(ctx->A); ((uint32_t *) resbuf)[1] = SWAP_LE32(ctx->B); ((uint32_t *) resbuf)[2] = SWAP_LE32(ctx->C); ((uint32_t *) resbuf)[3] = SWAP_LE32(ctx->D); return resbuf; }
int main(int argc, char *argv[]) { if (argc > 1) { int fd; struct stat sb; uint64_t size_to_md5 = 0; fd = open(argv[1], O_RDONLY); if (fd == -1) { perror("open"); exit(-1); } if (fstat(fd, &sb) == -1) { perror("fstat"); exit(-1); } size_t file_size = sb.st_size; void *addr = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, fd, 0); if (addr == MAP_FAILED) { perror("mmap"); exit(-1); } uint8_t *buf = (uint8_t *)malloc(file_size + (MD5_FILE_PADDING)); memcpy(buf, addr, file_size); munmap(addr, file_size); struct md5_context ctx; init_md5_ctx(&ctx, buf, file_size); //pad_md5(buf, file_size); uint64_t num_chunks = ctx.size / MD5_BLOCK_SIZE; if (((ctx.size % MD5_BLOCK_SIZE) == 0) && ctx.size != 0) num_chunks++; // go until the last block which may need to be padded for (;num_chunks > 1 ; num_chunks--) { md5_hash_block(&ctx); ctx.curptr += MD5_BLOCK_SIZE; } int need_another_block = pad_block(&ctx); md5_hash_block(&ctx); if (need_another_block) { ctx.curptr += MD5_BLOCK_SIZE; md5_hash_block(&ctx); } display_md5hash(&ctx); printf("\t%s\n", argv[1]); free(buf); close(fd); } return 0; }
void FAST_FUNC md5_hash(const void *buffer, size_t len, md5_ctx_t *ctx) { char *buf=(char *)buffer; /* RFC 1321 specifies the possible length of the file up to 2^64 bits, * Here we only track the number of bytes. */ ctx->total += len; // Process all input. while (len) { unsigned i = 64 - ctx->buflen; // Copy data into aligned buffer. if (i > len) i = len; memcpy(ctx->buffer + ctx->buflen, buf, i); len -= i; ctx->buflen += i; buf += i; // When buffer fills up, process it. if (ctx->buflen == 64) { md5_hash_block(ctx->buffer, ctx); ctx->buflen = 0; } } }