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 
35 #include "bswap.h"
36 #include "intreadwrite.h"
37 #include "mem.h"
38 #include "md5.h"
39 
40 typedef struct AVMD5 {
41  uint64_t len;
42  uint8_t block[64];
43  uint32_t ABCD[4];
44 } AVMD5;
45 
46 const int av_md5_size = sizeof(AVMD5);
47 
48 struct AVMD5 *av_md5_alloc(void)
49 {
50  return av_mallocz(sizeof(struct AVMD5));
51 }
52 
53 static const uint8_t S[4][4] = {
54  { 7, 12, 17, 22 }, /* round 1 */
55  { 5, 9, 14, 20 }, /* round 2 */
56  { 4, 11, 16, 23 }, /* round 3 */
57  { 6, 10, 15, 21 } /* round 4 */
58 };
59 
60 static const uint32_t T[64] = { // T[i]= fabs(sin(i+1)<<32)
61  0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, /* round 1 */
62  0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
63  0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
64  0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
65 
66  0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, /* round 2 */
67  0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
68  0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
69  0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
70 
71  0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, /* round 3 */
72  0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
73  0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
74  0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
75 
76  0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, /* round 4 */
77  0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
78  0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
79  0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
80 };
81 
82 #define CORE(i, a, b, c, d) \
83  do { \
84  t = S[i >> 4][i & 3]; \
85  a += T[i]; \
86  \
87  if (i < 32) { \
88  if (i < 16) \
89  a += (d ^ (b & (c ^ d))) + AV_RL32(X+( i & 15));\
90  else \
91  a += ((d & b) | (~d & c)) + AV_RL32(X+((1 + 5*i) & 15));\
92  } else { \
93  if (i < 48) \
94  a += (b ^ c ^ d) + AV_RL32(X+((5 + 3*i) & 15));\
95  else \
96  a += (c ^ (b | ~d)) + AV_RL32(X+(( 7*i) & 15));\
97  } \
98  a = b + (a << t | a >> (32 - t)); \
99  } while (0)
100 
101 static void body(uint32_t ABCD[4], const uint8_t *src, size_t nblocks)
102 {
103  const uint32_t *X;
104  uint32_t a, b, c, d, t;
105 
106  for (size_t n = 0; n < nblocks; n++) {
107  a = ABCD[3];
108  b = ABCD[2];
109  c = ABCD[1];
110  d = ABCD[0];
111 
112  X = (const uint32_t *)src + n * 16;
113 
114 #if CONFIG_SMALL
115  for (int i = 0; i < 64; i++) {
116  CORE(i, a, b, c, d);
117  t = d;
118  d = c;
119  c = b;
120  b = a;
121  a = t;
122  }
123 #else
124 #define CORE2(i) \
125  CORE(i, a, b, c, d); CORE((i + 1), d, a, b, c); \
126  CORE((i + 2), c, d, a, b); CORE((i + 3), b, c, d, a)
127 #define CORE4(i) CORE2(i); CORE2((i + 4)); CORE2((i + 8)); CORE2((i + 12))
128  CORE4(0);
129  CORE4(16);
130  CORE4(32);
131  CORE4(48);
132 #endif
133 
134  ABCD[0] += d;
135  ABCD[1] += c;
136  ABCD[2] += b;
137  ABCD[3] += a;
138  }
139 }
140 
142 {
143  ctx->len = 0;
144 
145  ctx->ABCD[0] = 0x10325476;
146  ctx->ABCD[1] = 0x98badcfe;
147  ctx->ABCD[2] = 0xefcdab89;
148  ctx->ABCD[3] = 0x67452301;
149 }
150 
151 void av_md5_update(AVMD5 *ctx, const uint8_t *src, size_t len)
152 {
153  const uint8_t *end;
154  int j;
155 
156  j = ctx->len & 63;
157  ctx->len += len;
158 
159  if (j) {
160  int cnt = FFMIN(len, 64 - j);
161  memcpy(ctx->block + j, src, cnt);
162  src += cnt;
163  len -= cnt;
164  if (j + cnt < 64)
165  return;
166  body(ctx->ABCD, ctx->block, 1);
167  }
168 
169  end = src + (len & ~63);
170  if (!HAVE_FAST_UNALIGNED && ((intptr_t)src & 3)) {
171  while (src < end) {
172  memcpy(ctx->block, src, 64);
173  body(ctx->ABCD, ctx->block, 1);
174  src += 64;
175  }
176  } else {
177  size_t nblocks = len / 64;
178  body(ctx->ABCD, src, nblocks);
179  src = end;
180  }
181  len &= 63;
182  if (len > 0)
183  memcpy(ctx->block, src, len);
184 }
185 
186 void av_md5_final(AVMD5 *ctx, uint8_t *dst)
187 {
188  int i;
189  uint64_t finalcount = av_le2ne64(ctx->len << 3);
190 
191  av_md5_update(ctx, "\200", 1);
192  while ((ctx->len & 63) != 56)
193  av_md5_update(ctx, "", 1);
194 
195  av_md5_update(ctx, (uint8_t *) &finalcount, 8);
196 
197  for (i = 0; i < 4; i++)
198  AV_WL32(dst + 4 * i, ctx->ABCD[3 - i]);
199 }
200 
201 void av_md5_sum(uint8_t *dst, const uint8_t *src, size_t len)
202 {
203  AVMD5 ctx;
204 
205  av_md5_init(&ctx);
206  av_md5_update(&ctx, src, len);
207  av_md5_final(&ctx, dst);
208 }
AVMD5::ABCD
uint32_t ABCD[4]
Definition: md5.c:43
AV_WL32
#define AV_WL32(p, v)
Definition: intreadwrite.h:426
X
@ X
Definition: vf_addroi.c:26
b
#define b
Definition: input.c:40
T
static const uint32_t T[64]
Definition: md5.c:60
av_md5_size
const int av_md5_size
Definition: md5.c:46
AVMD5
Definition: md5.c:40
intreadwrite.h
ctx
AVFormatContext * ctx
Definition: movenc.c:48
AVMD5::block
uint8_t block[64]
Definition: md5.c:42
src
#define src
Definition: vp8dsp.c:255
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:97
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:201
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:82
av_md5_init
void av_md5_init(AVMD5 *ctx)
Initialize MD5 hashing.
Definition: md5.c:141
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:271
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:263
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:186
CORE4
#define CORE4(i)
bswap.h
av_md5_alloc
struct AVMD5 * av_md5_alloc(void)
Allocate an AVMD5 context.
Definition: md5.c:48
body
static void body(uint32_t ABCD[4], const uint8_t *src, size_t nblocks)
Definition: md5.c:101
AVMD5::len
uint64_t len
Definition: md5.c:41
av_md5_update
void av_md5_update(AVMD5 *ctx, const uint8_t *src, size_t len)
Update hash value.
Definition: md5.c:151
mem.h
S
static const uint8_t S[4][4]
Definition: md5.c:53
d
d
Definition: ffmpeg_filter.c:153