1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* 2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. 3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * MD5 Message-Digest Algorithm (RFC 1321). 4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * 5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * Homepage: 6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * 8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * Author: 9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * Alexander Peslyak, better known as Solar Designer <solar at openwall.com> 10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * 11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * This software was written by Alexander Peslyak in 2001. No copyright is 12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * claimed, and the software is hereby placed in the public domain. 13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * In case this attempt to disclaim copyright and place the software in the 14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * public domain is deemed null and void, then the software is 15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the 16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * general public under the following terms: 17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * 18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * Redistribution and use in source and binary forms, with or without 19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * modification, are permitted. 20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * 21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * There's ABSOLUTELY NO WARRANTY, express or implied. 22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * 23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * (This is a heavily cut-down "BSD license".) 24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * 25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * This differs from Colin Plumb's older public domain implementation in that 26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * no exactly 32-bit integer data type is required (any 32-bit or wider 27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * unsigned integer data type will do), there's no compile-time endianness 28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * configuration, and the function prototypes match OpenSSL's. No code from 29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * Colin Plumb's implementation has been reused; this comment merely compares 30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * the properties of the two independent implementations. 31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * 32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * The primary goals of this implementation are portability and ease of use. 33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * It is meant to be fast, but not as fast as possible. Some known 34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * optimizations are not included to reduce source code size and avoid 35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * compile-time configuration. 36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov */ 37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifndef HAVE_OPENSSL 39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include <string.h> 41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "md5.h" 43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* 45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * The basic MD5 functions. 46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * 47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * F and G are optimized compared to their RFC 1321 definitions for 48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * architectures that lack an AND-NOT instruction, just like in Colin Plumb's 49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * implementation. 50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov */ 51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) 52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) 53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define H(x, y, z) ((x) ^ (y) ^ (z)) 54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define I(x, y, z) ((y) ^ ((x) | ~(z))) 55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* 57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * The MD5 transformation for all four rounds. 58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov */ 59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define STEP(f, a, b, c, d, x, t, s) \ 60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (a) += f((b), (c), (d)) + (x) + (t); \ 61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ 62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (a) += (b); 63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* 65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * SET reads 4 input bytes in little-endian byte order and stores them 66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * in a properly aligned word in host byte order. 67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * 68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * The check for little-endian architectures that tolerate unaligned 69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * memory accesses is just an optimization. Nothing will break if it 70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * doesn't work. 71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov */ 72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#if defined(__i386__) || defined(__x86_64__) || defined(__vax__) 73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define SET(n) \ 74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (*(MD5_u32plus *)&ptr[(n) * 4]) 75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define GET(n) \ 76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov SET(n) 77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else 78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define SET(n) \ 79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (ctx->block[(n)] = \ 80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (MD5_u32plus)ptr[(n) * 4] | \ 81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \ 82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \ 83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ((MD5_u32plus)ptr[(n) * 4 + 3] << 24)) 84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define GET(n) \ 85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (ctx->block[(n)]) 86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* 89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * This processes one or more 64-byte data blocks, but does NOT update 90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * the bit counters. There are no alignment requirements. 91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov */ 92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic void *body(MD5_CTX *ctx, void *data, unsigned long size) 93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned char *ptr; 95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov MD5_u32plus a, b, c, d; 96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov MD5_u32plus saved_a, saved_b, saved_c, saved_d; 97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ptr = (unsigned char *)data; 99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov a = ctx->a; 101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov b = ctx->b; 102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov c = ctx->c; 103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov d = ctx->d; 104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov do { 106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov saved_a = a; 107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov saved_b = b; 108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov saved_c = c; 109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov saved_d = d; 110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* Round 1 */ 112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7) 113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12) 114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(F, c, d, a, b, SET(2), 0x242070db, 17) 115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22) 116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7) 117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12) 118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(F, c, d, a, b, SET(6), 0xa8304613, 17) 119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(F, b, c, d, a, SET(7), 0xfd469501, 22) 120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(F, a, b, c, d, SET(8), 0x698098d8, 7) 121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12) 122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17) 123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22) 124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(F, a, b, c, d, SET(12), 0x6b901122, 7) 125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(F, d, a, b, c, SET(13), 0xfd987193, 12) 126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(F, c, d, a, b, SET(14), 0xa679438e, 17) 127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(F, b, c, d, a, SET(15), 0x49b40821, 22) 128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* Round 2 */ 130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5) 131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(G, d, a, b, c, GET(6), 0xc040b340, 9) 132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14) 133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20) 134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5) 135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(G, d, a, b, c, GET(10), 0x02441453, 9) 136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14) 137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20) 138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5) 139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9) 140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14) 141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20) 142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5) 143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9) 144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14) 145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20) 146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* Round 3 */ 148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4) 149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(H, d, a, b, c, GET(8), 0x8771f681, 11) 150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16) 151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23) 152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4) 153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11) 154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16) 155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23) 156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4) 157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11) 158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16) 159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(H, b, c, d, a, GET(6), 0x04881d05, 23) 160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4) 161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11) 162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16) 163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23) 164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* Round 4 */ 166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(I, a, b, c, d, GET(0), 0xf4292244, 6) 167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(I, d, a, b, c, GET(7), 0x432aff97, 10) 168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15) 169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21) 170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6) 171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10) 172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15) 173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21) 174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6) 175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10) 176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(I, c, d, a, b, GET(6), 0xa3014314, 15) 177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21) 178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6) 179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10) 180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15) 181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21) 182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov a += saved_a; 184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov b += saved_b; 185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov c += saved_c; 186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov d += saved_d; 187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ptr += 64; 189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } while (size -= 64); 190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ctx->a = a; 192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ctx->b = b; 193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ctx->c = c; 194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ctx->d = d; 195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return ptr; 197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid MD5_Init(MD5_CTX *ctx) 200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ctx->a = 0x67452301; 202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ctx->b = 0xefcdab89; 203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ctx->c = 0x98badcfe; 204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ctx->d = 0x10325476; 205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ctx->lo = 0; 207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ctx->hi = 0; 208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid MD5_Update(MD5_CTX *ctx, void *data, unsigned long size) 211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov MD5_u32plus saved_lo; 213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned long used, free; 214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov saved_lo = ctx->lo; 216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) 217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ctx->hi++; 218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ctx->hi += size >> 29; 219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov used = saved_lo & 0x3f; 221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (used) { 223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov free = 64 - used; 224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (size < free) { 226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memcpy(&ctx->buffer[used], data, size); 227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memcpy(&ctx->buffer[used], data, free); 231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov data = (unsigned char *)data + free; 232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov size -= free; 233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov body(ctx, ctx->buffer, 64); 234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (size >= 64) { 237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov data = body(ctx, data, size & ~(unsigned long)0x3f); 238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov size &= 0x3f; 239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memcpy(ctx->buffer, data, size); 242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid MD5_Final(unsigned char *result, MD5_CTX *ctx) 245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned long used, free; 247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov used = ctx->lo & 0x3f; 249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ctx->buffer[used++] = 0x80; 251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov free = 64 - used; 253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (free < 8) { 255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memset(&ctx->buffer[used], 0, free); 256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov body(ctx, ctx->buffer, 64); 257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov used = 0; 258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov free = 64; 259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memset(&ctx->buffer[used], 0, free - 8); 262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ctx->lo <<= 3; 264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ctx->buffer[56] = ctx->lo; 265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ctx->buffer[57] = ctx->lo >> 8; 266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ctx->buffer[58] = ctx->lo >> 16; 267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ctx->buffer[59] = ctx->lo >> 24; 268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ctx->buffer[60] = ctx->hi; 269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ctx->buffer[61] = ctx->hi >> 8; 270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ctx->buffer[62] = ctx->hi >> 16; 271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ctx->buffer[63] = ctx->hi >> 24; 272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov body(ctx, ctx->buffer, 64); 274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result[0] = ctx->a; 276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result[1] = ctx->a >> 8; 277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result[2] = ctx->a >> 16; 278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result[3] = ctx->a >> 24; 279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result[4] = ctx->b; 280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result[5] = ctx->b >> 8; 281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result[6] = ctx->b >> 16; 282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result[7] = ctx->b >> 24; 283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result[8] = ctx->c; 284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result[9] = ctx->c >> 8; 285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result[10] = ctx->c >> 16; 286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result[11] = ctx->c >> 24; 287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result[12] = ctx->d; 288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result[13] = ctx->d >> 8; 289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result[14] = ctx->d >> 16; 290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result[15] = ctx->d >> 24; 291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memset(ctx, 0, sizeof(*ctx)); 293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 296