void psMd4Update(psDigestContext_t * md, const unsigned char *buf, uint32 len) { uint32 n; psAssert(md != NULL); psAssert(buf != NULL); while (len > 0) { n = min(len, (64 - md->md4.curlen)); memcpy(md->md4.buf + md->md4.curlen, buf, (size_t)n); md->md4.curlen += n; buf += n; len -= n; /* is 64 bytes full? */ if (md->md4.curlen == 64) { md4_compress(md, md->md4.buf); #ifdef HAVE_NATIVE_INT64 md->md4.length += 512; #else n = (md->md4.lengthLo + 512) & 0xFFFFFFFFL; if (n < md->md4.lengthLo) { md->md4.lengthHi++; } md->md4.lengthLo = n; #endif /* HAVE_NATIVE_INT64 */ md->md4.curlen = 0; } } }
/** Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (16 bytes) @return CRYPT_OK if successful */ int md4_done(hash_state * md, unsigned char *out) { int i; LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); if (md->md4.curlen >= sizeof(md->md4.buf)) { return CRYPT_INVALID_ARG; } /* increase the length of the message */ md->md4.length += md->md4.curlen * 8; /* append the '1' bit */ md->md4.buf[md->md4.curlen++] = (unsigned char)0x80; /* if the length is currently above 56 bytes we append zeros * then compress. Then we can fall back to padding zeros and length * encoding like normal. */ if (md->md4.curlen > 56) { while (md->md4.curlen < 64) { md->md4.buf[md->md4.curlen++] = (unsigned char)0; } md4_compress(md, md->md4.buf); md->md4.curlen = 0; } /* pad upto 56 bytes of zeroes */ while (md->md4.curlen < 56) { md->md4.buf[md->md4.curlen++] = (unsigned char)0; } /* store length */ STORE64L(md->md4.length, md->md4.buf+56); md4_compress(md, md->md4.buf); /* copy output */ for (i = 0; i < 4; i++) { STORE32L(md->md4.state[i], out+(4*i)); } #ifdef LTC_CLEAN_STACK zeromem(md, sizeof(hash_state)); #endif return CRYPT_OK; }
int32 psMd4Final(psDigestContext_t * md, unsigned char *out) { int32 i; #ifndef HAVE_NATIVE_INT64 uint32 n; #endif psAssert(md != NULL); psAssert(out != NULL); if (md->md4.curlen >= sizeof(md->md4.buf)) { psTraceCrypto("psMd4Final error\n"); return PS_LIMIT_FAIL; } /* increase the length of the message */ #ifdef HAVE_NATIVE_INT64 md->md4.length += md->md4.curlen << 3; #else n = (md->md4.lengthLo + (md->md4.curlen << 3)) & 0xFFFFFFFFL; if (n < md->md4.lengthLo) { md->md4.lengthHi++; } md->md4.lengthHi += (md->md4.curlen >> 29); md->md4.lengthLo = n; #endif /* HAVE_NATIVE_INT64 */ /* append the '1' bit */ md->md4.buf[md->md4.curlen++] = (unsigned char)0x80; /* if the length is currently above 56 bytes we append zeros * then compress. Then we can fall back to padding zeros and length * encoding like normal. */ if (md->md4.curlen > 56) { while (md->md4.curlen < 64) { md->md4.buf[md->md4.curlen++] = (unsigned char)0; } md4_compress(md, md->md4.buf); md->md4.curlen = 0; } /* pad upto 56 bytes of zeroes */ while (md->md4.curlen < 56) { md->md4.buf[md->md4.curlen++] = (unsigned char)0; } /* store length */ #ifdef HAVE_NATIVE_INT64 STORE64L(md->md4.length, md->md4.buf+56); #else STORE32L(md->md4.lengthLo, md->md4.buf+56); STORE32L(md->md4.lengthHi, md->md4.buf+60); #endif /* HAVE_NATIVE_INT64 */ md4_compress(md, md->md4.buf); /* copy output */ for (i = 0; i < 4; i++) { STORE32L(md->md4.state[i], out+(4*i)); } memset(md, 0x0, sizeof(psDigestContext_t)); return PS_SUCCESS; }