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  int i av_unused;
104  const uint32_t *X;
105  uint32_t a, b, c, d, t;
106 
107  for (size_t n = 0; n < nblocks; n++) {
108  a = ABCD[3];
109  b = ABCD[2];
110  c = ABCD[1];
111  d = ABCD[0];
112 
113  X = (const uint32_t *)src + n * 16;
114 
115 #if CONFIG_SMALL
116  for (i = 0; i < 64; i++) {
117  CORE(i, a, b, c, d);
118  t = d;
119  d = c;
120  c = b;
121  b = a;
122  a = t;
123  }
124 #else
125 #define CORE2(i) \
126  CORE(i, a, b, c, d); CORE((i + 1), d, a, b, c); \
127  CORE((i + 2), c, d, a, b); CORE((i + 3), b, c, d, a)
128 #define CORE4(i) CORE2(i); CORE2((i + 4)); CORE2((i + 8)); CORE2((i + 12))
129  CORE4(0);
130  CORE4(16);
131  CORE4(32);
132  CORE4(48);
133 #endif
134 
135  ABCD[0] += d;
136  ABCD[1] += c;
137  ABCD[2] += b;
138  ABCD[3] += a;
139  }
140 }
141 
143 {
144  ctx->len = 0;
145 
146  ctx->ABCD[0] = 0x10325476;
147  ctx->ABCD[1] = 0x98badcfe;
148  ctx->ABCD[2] = 0xefcdab89;
149  ctx->ABCD[3] = 0x67452301;
150 }
151 
152 void av_md5_update(AVMD5 *ctx, const uint8_t *src, size_t len)
153 {
154  const uint8_t *end;
155  int j;
156 
157  j = ctx->len & 63;
158  ctx->len += len;
159 
160  if (j) {
161  int cnt = FFMIN(len, 64 - j);
162  memcpy(ctx->block + j, src, cnt);
163  src += cnt;
164  len -= cnt;
165  if (j + cnt < 64)
166  return;
167  body(ctx->ABCD, ctx->block, 1);
168  }
169 
170  end = src + (len & ~63);
171  if (!HAVE_FAST_UNALIGNED && ((intptr_t)src & 3)) {
172  while (src < end) {
173  memcpy(ctx->block, src, 64);
174  body(ctx->ABCD, ctx->block, 1);
175  src += 64;
176  }
177  } else {
178  size_t nblocks = len / 64;
179  body(ctx->ABCD, src, nblocks);
180  src = end;
181  }
182  len &= 63;
183  if (len > 0)
184  memcpy(ctx->block, src, len);
185 }
186 
187 void av_md5_final(AVMD5 *ctx, uint8_t *dst)
188 {
189  int i;
190  uint64_t finalcount = av_le2ne64(ctx->len << 3);
191 
192  av_md5_update(ctx, "\200", 1);
193  while ((ctx->len & 63) != 56)
194  av_md5_update(ctx, "", 1);
195 
196  av_md5_update(ctx, (uint8_t *) &finalcount, 8);
197 
198  for (i = 0; i < 4; i++)
199  AV_WL32(dst + 4 * i, ctx->ABCD[3 - i]);
200 }
201 
202 void av_md5_sum(uint8_t *dst, const uint8_t *src, size_t len)
203 {
204  AVMD5 ctx;
205 
206  av_md5_init(&ctx);
207  av_md5_update(&ctx, src, len);
208  av_md5_final(&ctx, dst);
209 }
AVMD5::ABCD
uint32_t ABCD[4]
Definition: md5.c:43
AV_WL32
#define AV_WL32(p, v)
Definition: intreadwrite.h:426
av_unused
#define av_unused
Definition: attributes.h:131
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
X
@ X
Definition: vf_addroi.c:26
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:202
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:142
i
int i
Definition: input.c:406
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:187
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:152
mem.h
S
static const uint8_t S[4][4]
Definition: md5.c:53
d
d
Definition: ffmpeg_filter.c:156