1/*
2 * Copyright 2017, DornerWorks
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * This data was produced by DornerWorks, Ltd. of Grand Rapids, MI, USA under
7 * a DARPA SBIR, Contract Number D16PC00107.
8 *
9 * Approved for Public Release, Distribution Unlimited.
10 *
11 */
12
13/*
14 * md5 crypt implementation
15 *
16 * original md5 crypt design is from Poul-Henning Kamp
17 * this implementation was created based on the code in freebsd
18 * at least 32bit int is assumed, key is limited and $1$ prefix is mandatory,
19 * on error "*" is returned
20 */
21#include <strops.h>
22#include <printf.h>
23#include <types.h>
24#include "../crypt_md5.h"
25
26/* public domain md5 implementation based on rfc1321 and libtomcrypt */
27
28static uint32_t rol(uint32_t n, int k)
29{
30    return (n << k) | (n >> (32 - k));
31}
32#define F(x,y,z) (z ^ (x & (y ^ z)))
33#define G(x,y,z) (y ^ (z & (y ^ x)))
34#define H(x,y,z) (x ^ y ^ z)
35#define I(x,y,z) (y ^ (x | ~z))
36#define FF(a,b,c,d,w,s,t) a += F(b,c,d) + w + t; a = rol(a,s) + b
37#define GG(a,b,c,d,w,s,t) a += G(b,c,d) + w + t; a = rol(a,s) + b
38#define HH(a,b,c,d,w,s,t) a += H(b,c,d) + w + t; a = rol(a,s) + b
39#define II(a,b,c,d,w,s,t) a += I(b,c,d) + w + t; a = rol(a,s) + b
40
41static const uint32_t tab[64] = {
42    0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
43    0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
44    0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
45    0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
46    0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
47    0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
48    0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
49    0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
50};
51
52static void processblock(md5_t *s, const uint8_t *buf)
53{
54    uint32_t i, W[16], a, b, c, d;
55
56    for (i = 0; i < 16; i++) {
57        W[i] = buf[4 * i];
58        W[i] |= (uint32_t)buf[4 * i + 1] << 8;
59        W[i] |= (uint32_t)buf[4 * i + 2] << 16;
60        W[i] |= (uint32_t)buf[4 * i + 3] << 24;
61    }
62
63    a = s->h[0];
64    b = s->h[1];
65    c = s->h[2];
66    d = s->h[3];
67
68    i = 0;
69    while (i < 16) {
70        FF(a, b, c, d, W[i],  7, tab[i]);
71        i++;
72        FF(d, a, b, c, W[i], 12, tab[i]);
73        i++;
74        FF(c, d, a, b, W[i], 17, tab[i]);
75        i++;
76        FF(b, c, d, a, W[i], 22, tab[i]);
77        i++;
78    }
79    while (i < 32) {
80        GG(a, b, c, d, W[(5 * i + 1) % 16],  5, tab[i]);
81        i++;
82        GG(d, a, b, c, W[(5 * i + 1) % 16],  9, tab[i]);
83        i++;
84        GG(c, d, a, b, W[(5 * i + 1) % 16], 14, tab[i]);
85        i++;
86        GG(b, c, d, a, W[(5 * i + 1) % 16], 20, tab[i]);
87        i++;
88    }
89    while (i < 48) {
90        HH(a, b, c, d, W[(3 * i + 5) % 16],  4, tab[i]);
91        i++;
92        HH(d, a, b, c, W[(3 * i + 5) % 16], 11, tab[i]);
93        i++;
94        HH(c, d, a, b, W[(3 * i + 5) % 16], 16, tab[i]);
95        i++;
96        HH(b, c, d, a, W[(3 * i + 5) % 16], 23, tab[i]);
97        i++;
98    }
99    while (i < 64) {
100        II(a, b, c, d, W[7 * i % 16],  6, tab[i]);
101        i++;
102        II(d, a, b, c, W[7 * i % 16], 10, tab[i]);
103        i++;
104        II(c, d, a, b, W[7 * i % 16], 15, tab[i]);
105        i++;
106        II(b, c, d, a, W[7 * i % 16], 21, tab[i]);
107        i++;
108    }
109
110    s->h[0] += a;
111    s->h[1] += b;
112    s->h[2] += c;
113    s->h[3] += d;
114}
115
116static void pad(md5_t *s)
117{
118    unsigned r = s->len % 64;
119
120    s->buf[r++] = 0x80;
121    if (r > 56) {
122        memset(s->buf + r, 0, 64 - r);
123        r = 0;
124        processblock(s, s->buf);
125    }
126    memset(s->buf + r, 0, 56 - r);
127    s->len *= 8;
128    s->buf[56] = s->len;
129    s->buf[57] = s->len >> 8;
130    s->buf[58] = s->len >> 16;
131    s->buf[59] = s->len >> 24;
132    s->buf[60] = s->len >> 32;
133    s->buf[61] = s->len >> 40;
134    s->buf[62] = s->len >> 48;
135    s->buf[63] = s->len >> 56;
136    processblock(s, s->buf);
137}
138
139void md5_init(md5_t *s)
140{
141    s->len = 0;
142    s->h[0] = 0x67452301;
143    s->h[1] = 0xefcdab89;
144    s->h[2] = 0x98badcfe;
145    s->h[3] = 0x10325476;
146}
147
148void md5_sum(md5_t *s, uint8_t *md)
149{
150    int i;
151
152    pad(s);
153    for (i = 0; i < 4; i++) {
154        md[4 * i] = s->h[i];
155        md[4 * i + 1] = s->h[i] >> 8;
156        md[4 * i + 2] = s->h[i] >> 16;
157        md[4 * i + 3] = s->h[i] >> 24;
158    }
159}
160
161void md5_update(md5_t *s, const void *m, unsigned long len)
162{
163    const uint8_t *p = m;
164    unsigned r = s->len % 64;
165    s->len += len;
166    if (r) {
167        if (len < 64 - r) {
168            memcpy(s->buf + r, p, len);
169            return;
170        }
171        memcpy(s->buf + r, p, 64 - r);
172        len -= 64 - r;
173        p += 64 - r;
174        processblock(s, s->buf);
175    }
176    for (; len >= 64; len -= 64, p += 64) {
177        processblock(s, p);
178    }
179    memcpy(s->buf, p, len);
180}
181