David Fletcher / Mbed 2 deprecated CC3000WebServer

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers md5.cpp Source File

md5.cpp

00001 /*
00002  * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
00003  * MD5 Message-Digest Algorithm (RFC 1321).
00004  *
00005  * Homepage:
00006  * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
00007  *
00008  * Author:
00009  * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
00010  *
00011  * This software was written by Alexander Peslyak in 2001.  No copyright is
00012  * claimed, and the software is hereby placed in the public domain.
00013  * In case this attempt to disclaim copyright and place the software in the
00014  * public domain is deemed null and void, then the software is
00015  * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
00016  * general public under the following terms:
00017  *
00018  * Redistribution and use in source and binary forms, with or without
00019  * modification, are permitted.
00020  *
00021  * There's ABSOLUTELY NO WARRANTY, express or implied.
00022  *
00023  * (This is a heavily cut-down "BSD license".)
00024  *
00025  * This differs from Colin Plumb's older public domain implementation in that
00026  * no exactly 32-bit integer data type is required (any 32-bit or wider
00027  * unsigned integer data type will do), there's no compile-time endianness
00028  * configuration, and the function prototypes match OpenSSL's.  No code from
00029  * Colin Plumb's implementation has been reused; this comment merely compares
00030  * the properties of the two independent implementations.
00031  *
00032  * The primary goals of this implementation are portability and ease of use.
00033  * It is meant to be fast, but not as fast as possible.  Some known
00034  * optimizations are not included to reduce source code size and avoid
00035  * compile-time configuration.
00036  */
00037 
00038 #ifndef HAVE_OPENSSL
00039 
00040 #include "mbed.h"
00041 #include <string.h>
00042 
00043 #include "md5.h"
00044 
00045 /*
00046  * The basic MD5 functions.
00047  *
00048  * F and G are optimized compared to their RFC 1321 definitions for
00049  * architectures that lack an AND-NOT instruction, just like in Colin Plumb's
00050  * implementation.
00051  */
00052 #define F(x, y, z)          ((z) ^ ((x) & ((y) ^ (z))))
00053 #define G(x, y, z)          ((y) ^ ((z) & ((x) ^ (y))))
00054 #define H(x, y, z)          ((x) ^ (y) ^ (z))
00055 #define I(x, y, z)          ((y) ^ ((x) | ~(z)))
00056 
00057 /*
00058  * The MD5 transformation for all four rounds.
00059  */
00060 #define STEP(f, a, b, c, d, x, t, s) \
00061     (a) += f((b), (c), (d)) + (x) + (t); \
00062     (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
00063     (a) += (b);
00064 
00065 /*
00066  * SET reads 4 input bytes in little-endian byte order and stores them
00067  * in a properly aligned word in host byte order.
00068  *
00069  * The check for little-endian architectures that tolerate unaligned
00070  * memory accesses is just an optimization.  Nothing will break if it
00071  * doesn't work.
00072  */
00073 #if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
00074 #define SET(n) \
00075     (*(MD5_u32plus *)&ptr[(n) * 4])
00076 #define GET(n) \
00077     SET(n)
00078 #else
00079 #define SET(n) \
00080     (ctx->block[(n)] = \
00081     (MD5_u32plus)ptr[(n) * 4] | \
00082     ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
00083     ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
00084     ((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
00085 #define GET(n) \
00086     (ctx->block[(n)])
00087 #endif
00088 
00089 /*
00090  * This processes one or more 64-byte data blocks, but does NOT update
00091  * the bit counters.  There are no alignment requirements.
00092  */
00093 static void *body(MD5_CTX *ctx, void *data, unsigned long size)
00094 {
00095     unsigned char *ptr;
00096     MD5_u32plus a, b, c, d;
00097     MD5_u32plus saved_a, saved_b, saved_c, saved_d;
00098 
00099     ptr = (unsigned char*)data;
00100 
00101     a = ctx->a;
00102     b = ctx->b;
00103     c = ctx->c;
00104     d = ctx->d;
00105 
00106     do {
00107         saved_a = a;
00108         saved_b = b;
00109         saved_c = c;
00110         saved_d = d;
00111 
00112 /* Round 1 */
00113         STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
00114         STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
00115         STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
00116         STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
00117         STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
00118         STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
00119         STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
00120         STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
00121         STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
00122         STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
00123         STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
00124         STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
00125         STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
00126         STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
00127         STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
00128         STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
00129 
00130 /* Round 2 */
00131         STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
00132         STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
00133         STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
00134         STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
00135         STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
00136         STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
00137         STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
00138         STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
00139         STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
00140         STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
00141         STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
00142         STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
00143         STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
00144         STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
00145         STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
00146         STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
00147 
00148 /* Round 3 */
00149         STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
00150         STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
00151         STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
00152         STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
00153         STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
00154         STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
00155         STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
00156         STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
00157         STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
00158         STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
00159         STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
00160         STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
00161         STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
00162         STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
00163         STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
00164         STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
00165 
00166 /* Round 4 */
00167         STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
00168         STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
00169         STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
00170         STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
00171         STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
00172         STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
00173         STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
00174         STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
00175         STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
00176         STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
00177         STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
00178         STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
00179         STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
00180         STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
00181         STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
00182         STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
00183 
00184         a += saved_a;
00185         b += saved_b;
00186         c += saved_c;
00187         d += saved_d;
00188 
00189         ptr += 64;
00190     } while (size -= 64);
00191 
00192     ctx->a = a;
00193     ctx->b = b;
00194     ctx->c = c;
00195     ctx->d = d;
00196 
00197     return ptr;
00198 }
00199 
00200 void MD5_Init(MD5_CTX *ctx)
00201 {
00202     ctx->a = 0x67452301;
00203     ctx->b = 0xefcdab89;
00204     ctx->c = 0x98badcfe;
00205     ctx->d = 0x10325476;
00206 
00207     ctx->lo = 0;
00208     ctx->hi = 0;
00209 }
00210 
00211 void MD5_Update(MD5_CTX *ctx, void *data, unsigned long size)
00212 {
00213     MD5_u32plus saved_lo;
00214     unsigned long used, free;
00215 
00216     saved_lo = ctx->lo;
00217     if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
00218         ctx->hi++;
00219     ctx->hi += size >> 29;
00220 
00221     used = saved_lo & 0x3f;
00222 
00223     if (used) {
00224         free = 64 - used;
00225 
00226         if (size < free) {
00227             memcpy(&ctx->buffer[used], data, size);
00228             return;
00229         }
00230 
00231         memcpy(&ctx->buffer[used], data, free);
00232         data = (unsigned char *)data + free;
00233         size -= free;
00234         body(ctx, ctx->buffer, 64);
00235     }
00236 
00237     if (size >= 64) {
00238         data = body(ctx, data, size & ~(unsigned long)0x3f);
00239         size &= 0x3f;
00240     }
00241 
00242     memcpy(ctx->buffer, data, size);
00243 }
00244 
00245 void MD5_Final(unsigned char *result, MD5_CTX *ctx)
00246 {
00247     unsigned long used, free;
00248 
00249     used = ctx->lo & 0x3f;
00250 
00251     ctx->buffer[used++] = 0x80;
00252 
00253     free = 64 - used;
00254 
00255     if (free < 8) {
00256         memset(&ctx->buffer[used], 0, free);
00257         body(ctx, ctx->buffer, 64);
00258         used = 0;
00259         free = 64;
00260     }
00261 
00262     memset(&ctx->buffer[used], 0, free - 8);
00263 
00264     ctx->lo <<= 3;
00265     ctx->buffer[56] = ctx->lo;
00266     ctx->buffer[57] = ctx->lo >> 8;
00267     ctx->buffer[58] = ctx->lo >> 16;
00268     ctx->buffer[59] = ctx->lo >> 24;
00269     ctx->buffer[60] = ctx->hi;
00270     ctx->buffer[61] = ctx->hi >> 8;
00271     ctx->buffer[62] = ctx->hi >> 16;
00272     ctx->buffer[63] = ctx->hi >> 24;
00273 
00274     body(ctx, ctx->buffer, 64);
00275 
00276     result[0] = ctx->a;
00277     result[1] = ctx->a >> 8;
00278     result[2] = ctx->a >> 16;
00279     result[3] = ctx->a >> 24;
00280     result[4] = ctx->b;
00281     result[5] = ctx->b >> 8;
00282     result[6] = ctx->b >> 16;
00283     result[7] = ctx->b >> 24;
00284     result[8] = ctx->c;
00285     result[9] = ctx->c >> 8;
00286     result[10] = ctx->c >> 16;
00287     result[11] = ctx->c >> 24;
00288     result[12] = ctx->d;
00289     result[13] = ctx->d >> 8;
00290     result[14] = ctx->d >> 16;
00291     result[15] = ctx->d >> 24;
00292 
00293     memset(ctx, 0, sizeof(*ctx));
00294 }
00295 
00296 #endif
00297