FFmpeg
md5.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006 Michael Niedermayer (michaelni@gmx.at)
3  * Copyright (C) 2003-2005 by Christopher R. Hertel (crh@ubiqx.mn.org)
4  *
5  * References:
6  * IETF RFC 1321: The MD5 Message-Digest Algorithm
7  * Ron Rivest. IETF, April, 1992
8  *
9  * based on http://ubiqx.org/libcifs/source/Auth/MD5.c
10  * from Christopher R. Hertel (crh@ubiqx.mn.org)
11  * Simplified, cleaned and IMO redundant comments removed by Michael.
12  *
13  * If you use gcc, then version 4.1 or later and -fomit-frame-pointer is
14  * strongly recommended.
15  *
16  * This file is part of FFmpeg.
17  *
18  * FFmpeg is free software; you can redistribute it and/or
19  * modify it under the terms of the GNU Lesser General Public
20  * License as published by the Free Software Foundation; either
21  * version 2.1 of the License, or (at your option) any later version.
22  *
23  * FFmpeg is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26  * Lesser General Public License for more details.
27  *
28  * You should have received a copy of the GNU Lesser General Public
29  * License along with FFmpeg; if not, write to the Free Software
30  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
31  */
32 
33 #include <stdint.h>
34 #include <string.h>
35 
36 #include "bswap.h"
37 #include "intreadwrite.h"
38 #include "macros.h"
39 #include "mem.h"
40 #include "md5.h"
41 
42 typedef struct AVMD5 {
43  uint64_t len;
44  uint8_t block[64];
45  uint32_t ABCD[4];
46 } AVMD5;
47 
48 const int av_md5_size = sizeof(AVMD5);
49 
50 struct AVMD5 *av_md5_alloc(void)
51 {
52  return av_mallocz(sizeof(struct AVMD5));
53 }
54 
55 static const uint8_t S[4][4] = {
56  { 7, 12, 17, 22 }, /* round 1 */
57  { 5, 9, 14, 20 }, /* round 2 */
58  { 4, 11, 16, 23 }, /* round 3 */
59  { 6, 10, 15, 21 } /* round 4 */
60 };
61 
62 static const uint32_t T[64] = { // T[i]= fabs(sin(i+1)<<32)
63  0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, /* round 1 */
64  0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
65  0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
66  0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
67 
68  0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, /* round 2 */
69  0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
70  0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
71  0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
72 
73  0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, /* round 3 */
74  0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
75  0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
76  0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
77 
78  0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, /* round 4 */
79  0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
80  0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
81  0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
82 };
83 
84 #define CORE(i, a, b, c, d) \
85  do { \
86  t = S[i >> 4][i & 3]; \
87  a += T[i]; \
88  \
89  if (i < 32) { \
90  if (i < 16) \
91  a += (d ^ (b & (c ^ d))) + AV_RL32(X+( i & 15));\
92  else \
93  a += ((d & b) | (~d & c)) + AV_RL32(X+((1 + 5*i) & 15));\
94  } else { \
95  if (i < 48) \
96  a += (b ^ c ^ d) + AV_RL32(X+((5 + 3*i) & 15));\
97  else \
98  a += (c ^ (b | ~d)) + AV_RL32(X+(( 7*i) & 15));\
99  } \
100  a = b + (a << t | a >> (32 - t)); \
101  } while (0)
102 
103 static void body(uint32_t ABCD[4], const uint8_t *src, size_t nblocks)
104 {
105  const uint32_t *X;
106  uint32_t a, b, c, d, t;
107 
108  for (size_t n = 0; n < nblocks; n++) {
109  a = ABCD[3];
110  b = ABCD[2];
111  c = ABCD[1];
112  d = ABCD[0];
113 
114  X = (const uint32_t *)src + n * 16;
115 
116 #if CONFIG_SMALL
117  for (int i = 0; i < 64; i++) {
118  CORE(i, a, b, c, d);
119  t = d;
120  d = c;
121  c = b;
122  b = a;
123  a = t;
124  }
125 #else
126 #define CORE2(i) \
127  CORE(i, a, b, c, d); CORE((i + 1), d, a, b, c); \
128  CORE((i + 2), c, d, a, b); CORE((i + 3), b, c, d, a)
129 #define CORE4(i) CORE2(i); CORE2((i + 4)); CORE2((i + 8)); CORE2((i + 12))
130  CORE4(0);
131  CORE4(16);
132  CORE4(32);
133  CORE4(48);
134 #endif
135 
136  ABCD[0] += d;
137  ABCD[1] += c;
138  ABCD[2] += b;
139  ABCD[3] += a;
140  }
141 }
142 
144 {
145  ctx->len = 0;
146 
147  ctx->ABCD[0] = 0x10325476;
148  ctx->ABCD[1] = 0x98badcfe;
149  ctx->ABCD[2] = 0xefcdab89;
150  ctx->ABCD[3] = 0x67452301;
151 }
152 
153 void av_md5_update(AVMD5 *ctx, const uint8_t *src, size_t len)
154 {
155  const uint8_t *end;
156  int j;
157 
158  j = ctx->len & 63;
159  ctx->len += len;
160 
161  if (j) {
162  int cnt = FFMIN(len, 64 - j);
163  memcpy(ctx->block + j, src, cnt);
164  src += cnt;
165  len -= cnt;
166  if (j + cnt < 64)
167  return;
168  body(ctx->ABCD, ctx->block, 1);
169  }
170 
171  end = src + (len & ~63);
172  if (!HAVE_FAST_UNALIGNED && ((intptr_t)src & 3)) {
173  while (src < end) {
174  memcpy(ctx->block, src, 64);
175  body(ctx->ABCD, ctx->block, 1);
176  src += 64;
177  }
178  } else {
179  size_t nblocks = len / 64;
180  body(ctx->ABCD, src, nblocks);
181  src = end;
182  }
183  len &= 63;
184  if (len > 0)
185  memcpy(ctx->block, src, len);
186 }
187 
188 void av_md5_final(AVMD5 *ctx, uint8_t *dst)
189 {
190  int i;
191  uint64_t finalcount = av_le2ne64(ctx->len << 3);
192 
193  av_md5_update(ctx, "\200", 1);
194  while ((ctx->len & 63) != 56)
195  av_md5_update(ctx, "", 1);
196 
197  av_md5_update(ctx, (uint8_t *) &finalcount, 8);
198 
199  for (i = 0; i < 4; i++)
200  AV_WL32(dst + 4 * i, ctx->ABCD[3 - i]);
201 }
202 
203 void av_md5_sum(uint8_t *dst, const uint8_t *src, size_t len)
204 {
205  AVMD5 ctx;
206 
207  av_md5_init(&ctx);
208  av_md5_update(&ctx, src, len);
209  av_md5_final(&ctx, dst);
210 }
AVMD5::ABCD
uint32_t ABCD[4]
Definition: md5.c:45
AV_WL32
#define AV_WL32(p, v)
Definition: intreadwrite.h:422
b
#define b
Definition: input.c:41
T
static const uint32_t T[64]
Definition: md5.c:62
macros.h
av_md5_size
const int av_md5_size
Definition: md5.c:48
AVMD5
Definition: md5.c:42
intreadwrite.h
ctx
AVFormatContext * ctx
Definition: movenc.c:49
AVMD5::block
uint8_t block[64]
Definition: md5.c:44
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
av_le2ne64
#define av_le2ne64(x)
Definition: bswap.h:93
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:83
av_md5_sum
void av_md5_sum(uint8_t *dst, const uint8_t *src, size_t len)
Hash an array of data.
Definition: md5.c:203
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
CORE
#define CORE(i, a, b, c, d)
Definition: md5.c:84
av_md5_init
void av_md5_init(AVMD5 *ctx)
Initialize MD5 hashing.
Definition: md5.c:143
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
md5.h
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:256
len
int len
Definition: vorbis_enc_data.h:426
av_md5_final
void av_md5_final(AVMD5 *ctx, uint8_t *dst)
Finish hashing and output digest value.
Definition: md5.c:188
CORE4
#define CORE4(i)
bswap.h
av_md5_alloc
struct AVMD5 * av_md5_alloc(void)
Allocate an AVMD5 context.
Definition: md5.c:50
body
static void body(uint32_t ABCD[4], const uint8_t *src, size_t nblocks)
Definition: md5.c:103
AVMD5::len
uint64_t len
Definition: md5.c:43
av_md5_update
void av_md5_update(AVMD5 *ctx, const uint8_t *src, size_t len)
Update hash value.
Definition: md5.c:153
X
@ X
Definition: vf_addroi.c:27
mem.h
S
static const uint8_t S[4][4]
Definition: md5.c:55
src
#define src
Definition: vp8dsp.c:248