Просмотр исходного кода

range function and md5 library

nmrr 2 лет назад
Родитель
Сommit
df84ffa38e
3 измененных файлов с 550 добавлено и 19 удалено
  1. 168 19
      flipper_atomicdiceroller.c
  2. 299 0
      md5.c
  3. 83 0
      md5.h

+ 168 - 19
flipper_atomicdiceroller.c

@@ -10,7 +10,7 @@
 #include <furi_hal_power.h>
 #include <furi_hal_power.h>
 #include <locale/locale.h>
 #include <locale/locale.h>
 #include <toolbox/crc32_calc.h>
 #include <toolbox/crc32_calc.h>
-#include <lib/toolbox/md5.h>
+#include "md5.h"
 
 
 #define SCREEN_SIZE_X 128
 #define SCREEN_SIZE_X 128
 #define SCREEN_SIZE_Y 64
 #define SCREEN_SIZE_Y 64
@@ -32,10 +32,12 @@ typedef struct {
 typedef struct {
 typedef struct {
     FuriMutex* mutex;
     FuriMutex* mutex;
     uint32_t cps;
     uint32_t cps;
-    uint32_t diceAvailiable;
+    uint8_t diceAvailiable;
     uint8_t dice;
     uint8_t dice;
     uint8_t method;
     uint8_t method;
     uint8_t pause;
     uint8_t pause;
+    uint8_t tickCounter;
+    uint8_t range;
 } mutexStruct;
 } mutexStruct;
 
 
 static void draw_callback(Canvas* canvas, void* ctx) 
 static void draw_callback(Canvas* canvas, void* ctx) 
@@ -51,17 +53,84 @@ static void draw_callback(Canvas* canvas, void* ctx)
     snprintf(buffer, sizeof(buffer), "%ld cps", mutexDraw.cps);
     snprintf(buffer, sizeof(buffer), "%ld cps", mutexDraw.cps);
     canvas_draw_str_aligned(canvas, 0, 10, AlignLeft, AlignBottom, buffer);
     canvas_draw_str_aligned(canvas, 0, 10, AlignLeft, AlignBottom, buffer);
 
 
-    snprintf(buffer, sizeof(buffer), "%lu/64", mutexDraw.diceAvailiable);
+    snprintf(buffer, sizeof(buffer), "%u/64", mutexDraw.diceAvailiable);
     canvas_draw_str_aligned(canvas, SCREEN_SIZE_X, 10, AlignRight, AlignBottom, buffer);
     canvas_draw_str_aligned(canvas, SCREEN_SIZE_X, 10, AlignRight, AlignBottom, buffer);
 
 
-    if (mutexDraw.method == 0) canvas_draw_str_aligned(canvas, 0, 20, AlignLeft, AlignBottom, "Hash: CRC32");
-    else canvas_draw_str_aligned(canvas, 0, 20, AlignLeft, AlignBottom, "Hash: MD5");
+    if (mutexDraw.method == 0)
+    {
+        if (mutexDraw.tickCounter < 2)
+        {
+            buffer[0] = '-';
+            buffer[1] = '-';
+            buffer[2] = '-';
+            buffer[3] = '\0';
+        }
+        else if (mutexDraw.tickCounter < 4)
+        {
+            buffer[0] = '+';
+            buffer[1] = '-';
+            buffer[2] = '-';
+            buffer[3] = '\0';
+        }
+        else if (mutexDraw.tickCounter < 6)
+        {
+            buffer[0] = '+';
+            buffer[1] = '+';
+            buffer[2] = '-';
+            buffer[3] = '\0';
+        }
+        else
+        {
+            buffer[0] = '+';
+            buffer[1] = '+';
+            buffer[2] = '+';
+            buffer[3] = '\0';
+        }
+    }
+    else 
+    {
+        if (mutexDraw.tickCounter < 8)
+        {
+            buffer[0] = '-';
+            buffer[1] = '-';
+            buffer[2] = '-';
+            buffer[3] = '\0';
+        }
+        else if (mutexDraw.tickCounter < 16)
+        {
+            buffer[0] = '+';
+            buffer[1] = '-';
+            buffer[2] = '-';
+            buffer[3] = '\0';
+        }
+        else if (mutexDraw.tickCounter < 24)
+        {
+            buffer[0] = '+';
+            buffer[1] = '+';
+            buffer[2] = '-';
+            buffer[3] = '\0';
+        }
+        else
+        {
+            buffer[0] = '+';
+            buffer[1] = '+';
+            buffer[2] = '+';
+            buffer[3] = '\0';
+        }
+    }
+    canvas_draw_str_aligned(canvas, SCREEN_SIZE_X-5, 20, AlignRight, AlignBottom, buffer);
+
+    if (mutexDraw.method == 0) canvas_draw_str_aligned(canvas, 0, 22, AlignLeft, AlignBottom, "Hash: CRC32");
+    else canvas_draw_str_aligned(canvas, 0, 22, AlignLeft, AlignBottom, "Hash: MD5");
+
+    if (mutexDraw.range == 0) canvas_draw_str_aligned(canvas, 0, 34, AlignLeft, AlignBottom, "Range: 0-1");
+    else canvas_draw_str_aligned(canvas, 0, 34, AlignLeft, AlignBottom, "Range: 1-6");
 
 
-    if (mutexDraw.dice != 0 && mutexDraw.pause == 0)
+    if (mutexDraw.pause == 0)
     {
     {
         canvas_set_font(canvas, FontBigNumbers);
         canvas_set_font(canvas, FontBigNumbers);
         snprintf(buffer, sizeof(buffer), "%u", mutexDraw.dice);
         snprintf(buffer, sizeof(buffer), "%u", mutexDraw.dice);
-        canvas_draw_str_aligned(canvas, SCREEN_SIZE_X/2, 50, AlignCenter, AlignBottom, buffer);
+        canvas_draw_str_aligned(canvas, SCREEN_SIZE_X/2, 54, AlignCenter, AlignBottom, buffer);
     }
     }
 }
 }
 
 
@@ -116,6 +185,8 @@ int32_t flipper_atomicdiceroller_app()
     mutexVal.dice = 0;
     mutexVal.dice = 0;
     mutexVal.diceAvailiable = 0;
     mutexVal.diceAvailiable = 0;
     mutexVal.method = 0;
     mutexVal.method = 0;
+    mutexVal.tickCounter = 0;
+    mutexVal.range = 0;
     uint32_t counter = 0;
     uint32_t counter = 0;
 
 
     mutexVal.mutex= furi_mutex_alloc(FuriMutexTypeNormal);
     mutexVal.mutex= furi_mutex_alloc(FuriMutexTypeNormal);
@@ -150,6 +221,7 @@ int32_t flipper_atomicdiceroller_app()
     uint8_t tickCounter = 0;
     uint8_t tickCounter = 0;
     uint32_t CRC32 = 0;
     uint32_t CRC32 = 0;
     uint8_t method = 0;
     uint8_t method = 0;
+    uint8_t range = 0;
 
 
     // MD5
     // MD5
     md5_context* md5_ctx = malloc(sizeof(md5_context));
     md5_context* md5_ctx = malloc(sizeof(md5_context));
@@ -205,8 +277,9 @@ int32_t flipper_atomicdiceroller_app()
                             tickCounter = 0;
                             tickCounter = 0;
                             furi_mutex_acquire(mutexVal.mutex, FuriWaitForever);
                             furi_mutex_acquire(mutexVal.mutex, FuriWaitForever);
                             mutexVal.method = 0;
                             mutexVal.method = 0;
-                            mutexVal.dice = 0;
+                            mutexVal.pause = 1;
                             mutexVal.diceAvailiable = 0;
                             mutexVal.diceAvailiable = 0;
+                            mutexVal.tickCounter = 0;
                             furi_mutex_release(mutexVal.mutex);
                             furi_mutex_release(mutexVal.mutex);
                             screenRefresh = 1;
                             screenRefresh = 1;
                         }
                         }
@@ -223,8 +296,47 @@ int32_t flipper_atomicdiceroller_app()
                             tickCounter = 0;
                             tickCounter = 0;
                             furi_mutex_acquire(mutexVal.mutex, FuriWaitForever);
                             furi_mutex_acquire(mutexVal.mutex, FuriWaitForever);
                             mutexVal.method = 1;
                             mutexVal.method = 1;
-                            mutexVal.dice = 0;
+                            mutexVal.pause = 1;
+                            mutexVal.diceAvailiable = 0;
+                            mutexVal.tickCounter = 0;
+                            furi_mutex_release(mutexVal.mutex);
+                            screenRefresh = 1;
+                        }
+                    }
+                    else if (event.input.key == InputKeyUp && event.input.type == InputTypeLong)
+                    {
+                        if (range > 0)
+                        {
+                            range--;
+                            diceBufferPositionWrite = 0;
+                            diceBufferPositionRead = 0;
+                            diceBufferCounter = 0;
+                            md5_starts(md5_ctx);
+                            tickCounter = 0;
+                            furi_mutex_acquire(mutexVal.mutex, FuriWaitForever);
+                            mutexVal.pause = 1;
+                            mutexVal.diceAvailiable = 0;
+                            mutexVal.tickCounter = 0;
+                            mutexVal.range = range;
+                            furi_mutex_release(mutexVal.mutex);
+                            screenRefresh = 1;
+                        }
+                    }
+                    else if (event.input.key == InputKeyDown && event.input.type == InputTypeLong)
+                    {
+                        if (range < 1)
+                        {
+                            range++;
+                            diceBufferPositionWrite = 0;
+                            diceBufferPositionRead = 0;
+                            diceBufferCounter = 0;
+                            md5_starts(md5_ctx);
+                            tickCounter = 0;
+                            furi_mutex_acquire(mutexVal.mutex, FuriWaitForever);
+                            mutexVal.pause = 1;
                             mutexVal.diceAvailiable = 0;
                             mutexVal.diceAvailiable = 0;
+                            mutexVal.tickCounter = 0;
+                            mutexVal.range = range;
                             furi_mutex_release(mutexVal.mutex);
                             furi_mutex_release(mutexVal.mutex);
                             screenRefresh = 1;
                             screenRefresh = 1;
                         }
                         }
@@ -235,6 +347,7 @@ int32_t flipper_atomicdiceroller_app()
             {
             {
                 furi_mutex_acquire(mutexVal.mutex, FuriWaitForever);
                 furi_mutex_acquire(mutexVal.mutex, FuriWaitForever);
                 mutexVal.cps = counter;
                 mutexVal.cps = counter;
+                mutexVal.tickCounter = tickCounter;
                 furi_mutex_release(mutexVal.mutex);
                 furi_mutex_release(mutexVal.mutex);
 
 
                 counter = 0;
                 counter = 0;
@@ -267,16 +380,11 @@ int32_t flipper_atomicdiceroller_app()
                         tickCounter++;
                         tickCounter++;
 
 
                         if (tickCounter == 8)
                         if (tickCounter == 8)
-                        {
-                            uint8_t localDice = CRC32 & 0b111;
-
-                            if (localDice == 0 || localDice == 7)
+                        {   
+                            if (range == 0)
                             {
                             {
-                                localDice = (diceBuffer[diceBufferPositionRead] >> 3) & 0b111;
-                            }
+                                uint8_t localDice = CRC32 & 0b1;
 
 
-                            if (localDice >= 1 && localDice <= 6)
-                            {
                                 diceBuffer[diceBufferPositionWrite] = localDice;
                                 diceBuffer[diceBufferPositionWrite] = localDice;
                                 diceBufferCounter++;
                                 diceBufferCounter++;
                                 if (diceBufferPositionWrite != 63) diceBufferPositionWrite++;
                                 if (diceBufferPositionWrite != 63) diceBufferPositionWrite++;
@@ -288,6 +396,29 @@ int32_t flipper_atomicdiceroller_app()
 
 
                                 screenRefresh = 1;
                                 screenRefresh = 1;
                             }
                             }
+                            else if (range == 1)
+                            {
+                                uint8_t localDice = CRC32 & 0b111;
+
+                                if (localDice == 0 || localDice == 7)
+                                {
+                                    localDice = (diceBuffer[diceBufferPositionRead] >> 3) & 0b111;
+                                }
+
+                                if (localDice >= 1 && localDice <= 6)
+                                {
+                                    diceBuffer[diceBufferPositionWrite] = localDice;
+                                    diceBufferCounter++;
+                                    if (diceBufferPositionWrite != 63) diceBufferPositionWrite++;
+                                    else diceBufferPositionWrite = 0;
+
+                                    furi_mutex_acquire(mutexVal.mutex, FuriWaitForever);
+                                    mutexVal.diceAvailiable = diceBufferCounter;
+                                    furi_mutex_release(mutexVal.mutex);
+
+                                    screenRefresh = 1;
+                                }
+                            }
 
 
                             CRC32 = 0;
                             CRC32 = 0;
                             tickCounter = 0;
                             tickCounter = 0;
@@ -312,9 +443,9 @@ int32_t flipper_atomicdiceroller_app()
 
 
                             for (uint8_t i=0;i<16;i++)
                             for (uint8_t i=0;i<16;i++)
                             {
                             {
-                                localDice = hash[i] & 0b111;
-                                if (localDice >= 1 && localDice <= 6)
+                                if (range == 0)
                                 {
                                 {
+                                    localDice = hash[i] & 0b1;
                                     diceBuffer[diceBufferPositionWrite] = localDice;
                                     diceBuffer[diceBufferPositionWrite] = localDice;
                                     diceBufferCounter++;
                                     diceBufferCounter++;
                                     if (diceBufferPositionWrite != 63) diceBufferPositionWrite++;
                                     if (diceBufferPositionWrite != 63) diceBufferPositionWrite++;
@@ -327,6 +458,24 @@ int32_t flipper_atomicdiceroller_app()
                                     screenRefresh = 1;
                                     screenRefresh = 1;
                                     break;
                                     break;
                                 }
                                 }
+                                else if (range == 1)
+                                {
+                                    localDice = hash[i] & 0b111;
+                                    if (localDice >= 1 && localDice <= 6)
+                                    {
+                                        diceBuffer[diceBufferPositionWrite] = localDice;
+                                        diceBufferCounter++;
+                                        if (diceBufferPositionWrite != 63) diceBufferPositionWrite++;
+                                        else diceBufferPositionWrite = 0;
+
+                                        furi_mutex_acquire(mutexVal.mutex, FuriWaitForever);
+                                        mutexVal.diceAvailiable = diceBufferCounter;
+                                        furi_mutex_release(mutexVal.mutex);
+
+                                        screenRefresh = 1;
+                                        break;
+                                    }
+                                }
                             }
                             }
 
 
                             md5_starts(md5_ctx);
                             md5_starts(md5_ctx);

+ 299 - 0
md5.c

@@ -0,0 +1,299 @@
+/*******************************************************************************
+*            Portions COPYRIGHT 2015 STMicroelectronics                        *
+*            Portions Copyright (C) 2006-2013, Brainspark B.V.                 *
+*******************************************************************************/
+
+/*
+ *  RFC 1321 compliant MD5 implementation
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The MD5 algorithm was designed by Ron Rivest in 1991.
+ *
+ *  http://www.ietf.org/rfc/rfc1321.txt
+ */
+
+/**
+  ******************************************************************************
+  * @file    md5.c
+  * @author  MCD Application Team
+  * @brief   This file has been modified to support the hardware Cryptographic and
+  *          Hash processors embedded in STM32F415xx/417xx/437xx/439xx/756xx devices.
+  *          This support is activated by defining the "USE_STM32F4XX_HW_CRYPTO"
+  *          or "USE_STM32F7XX_HW_CRYPTO" macro in PolarSSL config.h file.
+  ******************************************************************************
+  * @attention
+  *
+  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+  * You may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at:
+  *
+  *        http://www.st.com/software_license_agreement_liberty_v2
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  *
+  ******************************************************************************
+  */
+
+#include "md5.h"
+
+/*
+ * 32-bit integer manipulation macros (little endian)
+ */
+#ifndef GET_UINT32_LE
+#define GET_UINT32_LE(n, b, i)                                                 \
+    {                                                                          \
+        (n) = ((uint32_t)(b)[(i)]) | ((uint32_t)(b)[(i) + 1] << 8) |           \
+              ((uint32_t)(b)[(i) + 2] << 16) | ((uint32_t)(b)[(i) + 3] << 24); \
+    }
+#endif
+
+#ifndef PUT_UINT32_LE
+#define PUT_UINT32_LE(n, b, i)                     \
+    {                                              \
+        (b)[(i)] = (unsigned char)((n));           \
+        (b)[(i) + 1] = (unsigned char)((n) >> 8);  \
+        (b)[(i) + 2] = (unsigned char)((n) >> 16); \
+        (b)[(i) + 3] = (unsigned char)((n) >> 24); \
+    }
+#endif
+
+/*
+ * MD5 context setup
+ */
+void md5_starts(md5_context* ctx) {
+    ctx->total[0] = 0;
+    ctx->total[1] = 0;
+
+    ctx->state[0] = 0x67452301;
+    ctx->state[1] = 0xEFCDAB89;
+    ctx->state[2] = 0x98BADCFE;
+    ctx->state[3] = 0x10325476;
+}
+
+void md5_process(md5_context* ctx, const unsigned char data[64]) {
+    uint32_t X[16], A, B, C, D;
+
+    GET_UINT32_LE(X[0], data, 0);
+    GET_UINT32_LE(X[1], data, 4);
+    GET_UINT32_LE(X[2], data, 8);
+    GET_UINT32_LE(X[3], data, 12);
+    GET_UINT32_LE(X[4], data, 16);
+    GET_UINT32_LE(X[5], data, 20);
+    GET_UINT32_LE(X[6], data, 24);
+    GET_UINT32_LE(X[7], data, 28);
+    GET_UINT32_LE(X[8], data, 32);
+    GET_UINT32_LE(X[9], data, 36);
+    GET_UINT32_LE(X[10], data, 40);
+    GET_UINT32_LE(X[11], data, 44);
+    GET_UINT32_LE(X[12], data, 48);
+    GET_UINT32_LE(X[13], data, 52);
+    GET_UINT32_LE(X[14], data, 56);
+    GET_UINT32_LE(X[15], data, 60);
+
+#define S(x, n) (((x) << (n)) | (((x)&0xFFFFFFFF) >> (32 - (n))))
+
+#define P(a, b, c, d, k, s, t)      \
+    {                               \
+        a += F(b, c, d) + X[k] + t; \
+        a = S(a, s) + b;            \
+    }
+
+    A = ctx->state[0];
+    B = ctx->state[1];
+    C = ctx->state[2];
+    D = ctx->state[3];
+
+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
+
+    P(A, B, C, D, 0, 7, 0xD76AA478);
+    P(D, A, B, C, 1, 12, 0xE8C7B756);
+    P(C, D, A, B, 2, 17, 0x242070DB);
+    P(B, C, D, A, 3, 22, 0xC1BDCEEE);
+    P(A, B, C, D, 4, 7, 0xF57C0FAF);
+    P(D, A, B, C, 5, 12, 0x4787C62A);
+    P(C, D, A, B, 6, 17, 0xA8304613);
+    P(B, C, D, A, 7, 22, 0xFD469501);
+    P(A, B, C, D, 8, 7, 0x698098D8);
+    P(D, A, B, C, 9, 12, 0x8B44F7AF);
+    P(C, D, A, B, 10, 17, 0xFFFF5BB1);
+    P(B, C, D, A, 11, 22, 0x895CD7BE);
+    P(A, B, C, D, 12, 7, 0x6B901122);
+    P(D, A, B, C, 13, 12, 0xFD987193);
+    P(C, D, A, B, 14, 17, 0xA679438E);
+    P(B, C, D, A, 15, 22, 0x49B40821);
+
+#undef F
+
+#define F(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
+
+    P(A, B, C, D, 1, 5, 0xF61E2562);
+    P(D, A, B, C, 6, 9, 0xC040B340);
+    P(C, D, A, B, 11, 14, 0x265E5A51);
+    P(B, C, D, A, 0, 20, 0xE9B6C7AA);
+    P(A, B, C, D, 5, 5, 0xD62F105D);
+    P(D, A, B, C, 10, 9, 0x02441453);
+    P(C, D, A, B, 15, 14, 0xD8A1E681);
+    P(B, C, D, A, 4, 20, 0xE7D3FBC8);
+    P(A, B, C, D, 9, 5, 0x21E1CDE6);
+    P(D, A, B, C, 14, 9, 0xC33707D6);
+    P(C, D, A, B, 3, 14, 0xF4D50D87);
+    P(B, C, D, A, 8, 20, 0x455A14ED);
+    P(A, B, C, D, 13, 5, 0xA9E3E905);
+    P(D, A, B, C, 2, 9, 0xFCEFA3F8);
+    P(C, D, A, B, 7, 14, 0x676F02D9);
+    P(B, C, D, A, 12, 20, 0x8D2A4C8A);
+
+#undef F
+
+#define F(x, y, z) ((x) ^ (y) ^ (z))
+
+    P(A, B, C, D, 5, 4, 0xFFFA3942);
+    P(D, A, B, C, 8, 11, 0x8771F681);
+    P(C, D, A, B, 11, 16, 0x6D9D6122);
+    P(B, C, D, A, 14, 23, 0xFDE5380C);
+    P(A, B, C, D, 1, 4, 0xA4BEEA44);
+    P(D, A, B, C, 4, 11, 0x4BDECFA9);
+    P(C, D, A, B, 7, 16, 0xF6BB4B60);
+    P(B, C, D, A, 10, 23, 0xBEBFBC70);
+    P(A, B, C, D, 13, 4, 0x289B7EC6);
+    P(D, A, B, C, 0, 11, 0xEAA127FA);
+    P(C, D, A, B, 3, 16, 0xD4EF3085);
+    P(B, C, D, A, 6, 23, 0x04881D05);
+    P(A, B, C, D, 9, 4, 0xD9D4D039);
+    P(D, A, B, C, 12, 11, 0xE6DB99E5);
+    P(C, D, A, B, 15, 16, 0x1FA27CF8);
+    P(B, C, D, A, 2, 23, 0xC4AC5665);
+
+#undef F
+
+#define F(x, y, z) ((y) ^ ((x) | ~(z)))
+
+    P(A, B, C, D, 0, 6, 0xF4292244);
+    P(D, A, B, C, 7, 10, 0x432AFF97);
+    P(C, D, A, B, 14, 15, 0xAB9423A7);
+    P(B, C, D, A, 5, 21, 0xFC93A039);
+    P(A, B, C, D, 12, 6, 0x655B59C3);
+    P(D, A, B, C, 3, 10, 0x8F0CCC92);
+    P(C, D, A, B, 10, 15, 0xFFEFF47D);
+    P(B, C, D, A, 1, 21, 0x85845DD1);
+    P(A, B, C, D, 8, 6, 0x6FA87E4F);
+    P(D, A, B, C, 15, 10, 0xFE2CE6E0);
+    P(C, D, A, B, 6, 15, 0xA3014314);
+    P(B, C, D, A, 13, 21, 0x4E0811A1);
+    P(A, B, C, D, 4, 6, 0xF7537E82);
+    P(D, A, B, C, 11, 10, 0xBD3AF235);
+    P(C, D, A, B, 2, 15, 0x2AD7D2BB);
+    P(B, C, D, A, 9, 21, 0xEB86D391);
+
+#undef F
+
+    ctx->state[0] += A;
+    ctx->state[1] += B;
+    ctx->state[2] += C;
+    ctx->state[3] += D;
+}
+
+/*
+ * MD5 process buffer
+ */
+void md5_update(md5_context* ctx, const unsigned char* input, size_t ilen) {
+    size_t fill;
+    uint32_t left;
+
+    if(ilen <= 0) return;
+
+    left = ctx->total[0] & 0x3F;
+    fill = 64 - left;
+
+    ctx->total[0] += (uint32_t)ilen;
+    ctx->total[0] &= 0xFFFFFFFF;
+
+    if(ctx->total[0] < (uint32_t)ilen) ctx->total[1]++;
+
+    if(left && ilen >= fill) {
+        memcpy((void*)(ctx->buffer + left), input, fill);
+        md5_process(ctx, ctx->buffer);
+        input += fill;
+        ilen -= fill;
+        left = 0;
+    }
+
+    while(ilen >= 64) {
+        md5_process(ctx, input);
+        input += 64;
+        ilen -= 64;
+    }
+
+    if(ilen > 0) {
+        memcpy((void*)(ctx->buffer + left), input, ilen);
+    }
+}
+
+static const unsigned char md5_padding[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                              0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                              0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                              0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+/*
+ * MD5 final digest
+ */
+void md5_finish(md5_context* ctx, unsigned char output[16]) {
+    uint32_t last, padn;
+    uint32_t high, low;
+    unsigned char msglen[8];
+
+    high = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
+    low = (ctx->total[0] << 3);
+
+    PUT_UINT32_LE(low, msglen, 0);
+    PUT_UINT32_LE(high, msglen, 4);
+
+    last = ctx->total[0] & 0x3F;
+    padn = (last < 56) ? (56 - last) : (120 - last);
+
+    md5_update(ctx, md5_padding, padn);
+    md5_update(ctx, msglen, 8);
+
+    PUT_UINT32_LE(ctx->state[0], output, 0);
+    PUT_UINT32_LE(ctx->state[1], output, 4);
+    PUT_UINT32_LE(ctx->state[2], output, 8);
+    PUT_UINT32_LE(ctx->state[3], output, 12);
+}
+
+/*
+ * output = MD5( input buffer )
+ */
+void md5(const unsigned char* input, size_t ilen, unsigned char output[16]) {
+    md5_context ctx;
+
+    md5_starts(&ctx);
+    md5_update(&ctx, input, ilen);
+    md5_finish(&ctx, output);
+
+    memset(&ctx, 0, sizeof(md5_context)); //-V597
+}

+ 83 - 0
md5.h

@@ -0,0 +1,83 @@
+/**
+ * \file md5.h
+ *
+ * \brief MD5 message digest algorithm (hash function)
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+/**
+ * \brief          MD5 context structure
+ */
+typedef struct {
+    uint32_t total[2]; /*!< number of bytes processed  */
+    uint32_t state[4]; /*!< intermediate digest state  */
+    unsigned char buffer[64]; /*!< data block being processed */
+} md5_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          MD5 context setup
+ *
+ * \param ctx      context to be initialized
+ */
+void md5_starts(md5_context* ctx);
+
+/**
+ * \brief          MD5 process buffer
+ *
+ * \param ctx      MD5 context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void md5_update(md5_context* ctx, const unsigned char* input, size_t ilen);
+
+/**
+ * \brief          MD5 final digest
+ *
+ * \param ctx      MD5 context
+ * \param output   MD5 checksum result
+ */
+void md5_finish(md5_context* ctx, unsigned char output[16]);
+
+/* Internal use */
+void md5_process(md5_context* ctx, const unsigned char data[64]);
+
+/**
+ * \brief          Output = MD5( input buffer )
+ *
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   MD5 checksum result
+ */
+void md5(const unsigned char* input, size_t ilen, unsigned char output[16]);
+
+#ifdef __cplusplus
+}
+#endif