LCOV - code coverage report
Current view: top level - DCPS - Hash.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 140 155 90.3 %
Date: 2023-04-30 01:32:43 Functions: 5 5 100.0 %

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

Generated by: LCOV version 1.16