"Fossies" - the Fresh Open Source Software Archive

Member "msmtp-1.8.5/src/md5.c" (12 Dec 2018, 8743 Bytes) of package /linux/privat/msmtp-1.8.5.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "md5.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.8.1_vs_1.8.2.

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