Satellite Observers Workbench. NOT yet complete, just published for forum posters to \"cherry pick\" pieces of code as requiered as an example.

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers md5.c Source File

md5.c

00001 /****************************************************************************
00002  *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
00003  *    
00004  *    This file is part of the Satellite Observers Workbench (SOWB).
00005  *
00006  *    SOWB is free software: you can redistribute it and/or modify
00007  *    it under the terms of the GNU General Public License as published by
00008  *    the Free Software Foundation, either version 3 of the License, or
00009  *    (at your option) any later version.
00010  *
00011  *    SOWB is distributed in the hope that it will be useful,
00012  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *    GNU General Public License for more details.
00015  *
00016  *    You should have received a copy of the GNU General Public License
00017  *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
00018  *
00019  *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
00020  *    
00021  ***************************************************************************/
00022 
00023 /*
00024     Not even sure where I lifted this code now, but I think it was the
00025     FreeBSD project. So any copyright that is attributable to that project
00026     and the BSD license is acknowledged. This module is dual licensed:-
00027     
00028     http://www.opensource.org/licenses/bsd-license.php
00029     
00030     Copyright (c) 2010, Stellar Technologies Ltd/Andy Kirkham
00031     All rights reserved.
00032 
00033     Redistribution and use in source and binary forms, with or without modification, 
00034     are permitted provided that the following conditions are met:
00035 
00036     * Redistributions of source code must retain the above copyright notice, this 
00037       list of conditions and the following disclaimer.
00038     * Redistributions in binary form must reproduce the above copyright notice, 
00039       this list of conditions and the following disclaimer in the documentation 
00040       and/or other materials provided with the distribution.
00041     * Neither the name of the <ORGANIZATION> nor the names of its contributors may 
00042       be used to endorse or promote products derived from this software without 
00043       specific prior written permission.
00044 
00045     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
00046     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
00047     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
00048     ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
00049     LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
00050     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
00051     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
00052     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
00053     NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 
00054     IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00055     
00056     Additionally see http://www.freebsd.org/copyright/license.html
00057 */
00058 
00059 #include "sowb.h"
00060 
00061 /**
00062  * MD5 context structure.
00063  */
00064 typedef struct {
00065     uint32_t lo, hi;
00066     uint32_t a, b, c, d;
00067     unsigned char buffer[64];
00068     uint32_t block[16];
00069 } MD5_CTX;
00070 
00071 /* Used to create human text for MD5 */
00072 static const char hexits[17] = "0123456789ABCDEF";
00073 
00074 /**
00075  * Internal function prototypes.
00076  */
00077 static void make_digest(char *md5str, unsigned char *digest);
00078 static void md5_init(MD5_CTX *);
00079 static void md5_update(MD5_CTX *, const void *, unsigned int);
00080 static void md5_final(unsigned char *, MD5_CTX *);
00081 static const void *body(MD5_CTX *, const void *, unsigned int);
00082 
00083 void md5(const char *s, char *md5str) {
00084 
00085     // A local MD5 context.
00086     MD5_CTX context;
00087 
00088     // Place to store the raw MD5 digest.
00089     unsigned char digest[16];
00090 
00091     // Clear the output string and initialise the context.
00092     md5str[0] = '\0';
00093     md5_init(&context);
00094 
00095     // Make the MD5 and finalise.
00096     md5_update(&context, s, strlen(s));
00097     md5_final(digest, &context);
00098 
00099     // Convert the binary digest into human text in the caller's output buffer.
00100     make_digest(md5str, digest);
00101 }
00102 
00103 /**
00104  * md5_short
00105  *
00106  * As MD5 function but selects 5 fixed characters
00107  * from the 32 generated to return a short name.
00108  */
00109 void md5_short(const char *s, char *md5str, int d) {
00110     char temp[33];
00111     static const int day[7][5] = {
00112       { 18,  3,  8, 27, 19 }, // 01
00113       { 12, 11,  6, 21, 15 }, // 02
00114       { 27, 14, 12,  4, 11 }, // 03
00115       { 12, 18, 13,  6,  2 }, // 04
00116       { 29, 13,  8,  1, 15 }, // 05
00117       { 13, 12,  9, 30, 22 }, // 06
00118       { 29, 31,  2,  5, 14 }  // 07
00119     };
00120         
00121     // Get the full MD5 string.
00122     md5(s, temp);
00123     
00124     // Ensure we stay within our array boundaries.
00125     d &= 0x7;
00126     
00127     // Get the shortened version of the MD5.
00128     md5str[0] = temp[day[d][0]];
00129     md5str[1] = temp[day[d][1]];
00130     md5str[2] = temp[day[d][2]];
00131     md5str[3] = temp[day[d][3]];
00132     md5str[4] = temp[day[d][4]];
00133     md5str[5] = '\0';
00134 }
00135 
00136 static void make_digest(char *md5str, unsigned char *digest) {
00137     int i;
00138     
00139     for (i = 0; i < 16; i++) {
00140         md5str[i * 2]       = hexits[digest[i] >> 4];
00141         md5str[(i * 2) + 1] = hexits[digest[i] & 0x0F];
00142     }
00143     
00144     md5str[32] = '\0';
00145 }
00146 
00147 /*
00148  * This is an OpenSSL-compatible implementation of the RSA Data Security,
00149  * Inc. MD5 Message-Digest Algorithm (RFC 1321).
00150  *
00151  * Written by Solar Designer <solar at openwall.com> in 2001, and placed
00152  * in the public domain.  There's absolutely no warranty.
00153  *
00154  * This differs from Colin Plumb's older public domain implementation in
00155  * that no 32-bit integer data type is required, there's no compile-time
00156  * endianness configuration, and the function prototypes match OpenSSL's.
00157  * The primary goals are portability and ease of use.
00158  *
00159  * This implementation is meant to be fast, but not as fast as possible.
00160  * Some known optimizations are not included to reduce source code size
00161  * and avoid compile-time configuration.
00162  */
00163 
00164 
00165 /*
00166  * The basic MD5 functions.
00167  *
00168  * F and G are optimized compared to their RFC 1321 definitions for
00169  * architectures that lack an AND-NOT instruction, just like in Colin Plumb's
00170  * implementation.
00171  */
00172 #define F(x, y, z)            ((z) ^ ((x) & ((y) ^ (z))))
00173 #define G(x, y, z)            ((y) ^ ((z) & ((x) ^ (y))))
00174 #define H(x, y, z)            ((x) ^ (y) ^ (z))
00175 #define I(x, y, z)            ((y) ^ ((x) | ~(z)))
00176 
00177 /*
00178  * The MD5 transformation for all four rounds.
00179  */
00180 #define STEP(f, a, b, c, d, x, t, s) \
00181     (a) += f((b), (c), (d)) + (x) + (t); \
00182     (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
00183     (a) += (b);
00184 
00185 # define SET(n) \
00186     (ctx->block[(n)] = \
00187     (uint32_t)ptr[(n) * 4] | \
00188     ((uint32_t)ptr[(n) * 4 + 1] << 8) | \
00189     ((uint32_t)ptr[(n) * 4 + 2] << 16) | \
00190     ((uint32_t)ptr[(n) * 4 + 3] << 24))
00191 # define GET(n) \
00192     (ctx->block[(n)])
00193 
00194 /*
00195  * This processes one or more 64-byte data blocks, but does NOT update
00196  * the bit counters.  There are no alignment requirements.
00197  */
00198 static const void *body(MD5_CTX *ctx, const void *data, unsigned int size) {
00199     const unsigned char *ptr;
00200     uint32_t a, b, c, d;
00201     uint32_t saved_a, saved_b, saved_c, saved_d;
00202 
00203     ptr = (const unsigned char *)data;
00204 
00205     a = ctx->a;
00206     b = ctx->b;
00207     c = ctx->c;
00208     d = ctx->d;
00209 
00210     do {
00211         saved_a = a;
00212         saved_b = b;
00213         saved_c = c;
00214         saved_d = d;
00215 
00216         /* Round 1 */
00217         STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
00218         STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
00219         STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
00220         STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
00221         STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
00222         STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
00223         STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
00224         STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
00225         STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
00226         STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
00227         STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
00228         STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
00229         STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
00230         STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
00231         STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
00232         STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
00233 
00234         /* Round 2 */
00235         STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
00236         STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
00237         STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
00238         STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
00239         STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
00240         STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
00241         STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
00242         STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
00243         STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
00244         STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
00245         STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
00246         STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
00247         STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
00248         STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
00249         STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
00250         STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
00251 
00252         /* Round 3 */
00253         STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
00254         STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
00255         STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
00256         STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
00257         STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
00258         STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
00259         STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
00260         STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
00261         STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
00262         STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
00263         STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
00264         STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
00265         STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
00266         STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
00267         STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
00268         STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
00269 
00270         /* Round 4 */
00271         STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
00272         STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
00273         STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
00274         STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
00275         STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
00276         STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
00277         STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
00278         STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
00279         STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
00280         STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
00281         STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
00282         STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
00283         STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
00284         STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
00285         STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
00286         STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
00287 
00288         a += saved_a;
00289         b += saved_b;
00290         c += saved_c;
00291         d += saved_d;
00292 
00293         ptr += 64;
00294     } while (size -= 64);
00295 
00296     ctx->a = a;
00297     ctx->b = b;
00298     ctx->c = c;
00299     ctx->d = d;
00300 
00301     return ptr;
00302 }
00303 
00304 static void md5_init(MD5_CTX *ctx) {
00305     ctx->a = 0x67452301;
00306     ctx->b = 0xefcdab89;
00307     ctx->c = 0x98badcfe;
00308     ctx->d = 0x10325476;
00309 
00310     ctx->lo = 0;
00311     ctx->hi = 0;
00312 }
00313 
00314 static void md5_update(MD5_CTX *ctx, const void *data, unsigned int size) {
00315     uint32_t saved_lo;
00316     uint32_t used, free;
00317     
00318     saved_lo = ctx->lo;
00319     if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) {
00320         ctx->hi++;
00321     }
00322     ctx->hi += size >> 29;
00323 
00324     used = saved_lo & 0x3f;
00325 
00326     if (used) {
00327         free = 64 - used;
00328 
00329         if (size < free) {
00330             memcpy(&ctx->buffer[used], data, size);
00331             return;
00332         }
00333 
00334         memcpy(&ctx->buffer[used], data, free);
00335         data = (unsigned char *)data + free;
00336         size -= free;
00337         body(ctx, ctx->buffer, 64);
00338     }
00339 
00340     if (size >= 64) {
00341         data = body(ctx, data, size & ~(size_t)0x3f);
00342         size &= 0x3f;
00343     }
00344 
00345     memcpy(ctx->buffer, data, size);
00346 }
00347 
00348 static void md5_final(unsigned char *result, MD5_CTX *ctx) {
00349     uint32_t used, free;
00350     
00351     used = ctx->lo & 0x3f;
00352     
00353     ctx->buffer[used++] = 0x80;
00354 
00355     free = 64 - used;
00356 
00357     if (free < 8) {
00358         memset(&ctx->buffer[used], 0, free);
00359         body(ctx, ctx->buffer, 64);
00360         used = 0;
00361         free = 64;
00362     }
00363 
00364     memset(&ctx->buffer[used], 0, free - 8);
00365 
00366     ctx->lo <<= 3;
00367     ctx->buffer[56] = (unsigned char)ctx->lo;
00368     ctx->buffer[57] = (unsigned char)(ctx->lo >> 8);
00369     ctx->buffer[58] = (unsigned char)(ctx->lo >> 16);
00370     ctx->buffer[59] = (unsigned char)(ctx->lo >> 24);
00371     ctx->buffer[60] = (unsigned char)(ctx->hi);
00372     ctx->buffer[61] = (unsigned char)(ctx->hi >> 8);
00373     ctx->buffer[62] = (unsigned char)(ctx->hi >> 16);
00374     ctx->buffer[63] = (unsigned char)(ctx->hi >> 24);
00375 
00376     body(ctx, ctx->buffer, 64);
00377 
00378     result[0] = (unsigned char)ctx->a;
00379     result[1] = (unsigned char)(ctx->a >> 8);
00380     result[2] = (unsigned char)(ctx->a >> 16);
00381     result[3] = (unsigned char)(ctx->a >> 24);
00382     result[4] = (unsigned char)ctx->b;
00383     result[5] = (unsigned char)(ctx->b >> 8);
00384     result[6] = (unsigned char)(ctx->b >> 16);
00385     result[7] = (unsigned char)(ctx->b >> 24);
00386     result[8] = (unsigned char)ctx->c;
00387     result[9] = (unsigned char)(ctx->c >> 8);
00388     result[10] = (unsigned char)(ctx->c >> 16);
00389     result[11] = (unsigned char)(ctx->c >> 24);
00390     result[12] = (unsigned char)ctx->d;
00391     result[13] = (unsigned char)(ctx->d >> 8);
00392     result[14] = (unsigned char)(ctx->d >> 16);
00393     result[15] = (unsigned char)(ctx->d >> 24);
00394 
00395     memset(ctx, 0, sizeof(*ctx));
00396 }