annotate md5.c @ 728:1fa3820b1a84 libavutil

ARM asm for AV_RN*() ARMv6 and later support unaligned loads and stores for single word/halfword but not double/multiple. GCC is ignorant of this and will always use bytewise accesses for unaligned data. Casting to an int32_t pointer is dangerous since a load/store double or multiple instruction might be used (this happens with some code in FFmpeg). Implementing the AV_[RW]* macros with inline asm using only supported instructions gives fast and safe unaligned accesses. ARM RVCT does the right thing with generic code. This gives an overall speedup of up to 10%.
author mru
date Sat, 18 Apr 2009 00:00:28 +0000
parents 8c48a1b999a3
children 22a58fc2125d
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
45
31c84858af22 md5 support
michael
parents:
diff changeset
1 /*
31c84858af22 md5 support
michael
parents:
diff changeset
2 * Copyright (C) 2006 Michael Niedermayer (michaelni@gmx.at)
31c84858af22 md5 support
michael
parents:
diff changeset
3 * Copyright (C) 2003-2005 by Christopher R. Hertel (crh@ubiqx.mn.org)
59
f40e091f7716 Add proper LGPL header.
diego
parents: 58
diff changeset
4 *
357
791ee8a14d71 Group all copyright and author notices together.
diego
parents: 339
diff changeset
5 * References:
791ee8a14d71 Group all copyright and author notices together.
diego
parents: 339
diff changeset
6 * IETF RFC 1321: The MD5 Message-Digest Algorithm
791ee8a14d71 Group all copyright and author notices together.
diego
parents: 339
diff changeset
7 * Ron Rivest. IETF, April, 1992
791ee8a14d71 Group all copyright and author notices together.
diego
parents: 339
diff changeset
8 *
791ee8a14d71 Group all copyright and author notices together.
diego
parents: 339
diff changeset
9 * based on http://ubiqx.org/libcifs/source/Auth/MD5.c
791ee8a14d71 Group all copyright and author notices together.
diego
parents: 339
diff changeset
10 * from Christopher R. Hertel (crh@ubiqx.mn.org)
791ee8a14d71 Group all copyright and author notices together.
diego
parents: 339
diff changeset
11 * Simplified, cleaned and IMO redundant comments removed by michael.
791ee8a14d71 Group all copyright and author notices together.
diego
parents: 339
diff changeset
12 *
791ee8a14d71 Group all copyright and author notices together.
diego
parents: 339
diff changeset
13 * If you use gcc, then version 4.1 or later and -fomit-frame-pointer is
791ee8a14d71 Group all copyright and author notices together.
diego
parents: 339
diff changeset
14 * strongly recommended.
791ee8a14d71 Group all copyright and author notices together.
diego
parents: 339
diff changeset
15 *
116
d76a36742464 Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents: 59
diff changeset
16 * This file is part of FFmpeg.
d76a36742464 Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents: 59
diff changeset
17 *
d76a36742464 Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents: 59
diff changeset
18 * FFmpeg is free software; you can redistribute it and/or
59
f40e091f7716 Add proper LGPL header.
diego
parents: 58
diff changeset
19 * modify it under the terms of the GNU Lesser General Public
f40e091f7716 Add proper LGPL header.
diego
parents: 58
diff changeset
20 * License as published by the Free Software Foundation; either
116
d76a36742464 Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents: 59
diff changeset
21 * version 2.1 of the License, or (at your option) any later version.
59
f40e091f7716 Add proper LGPL header.
diego
parents: 58
diff changeset
22 *
116
d76a36742464 Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents: 59
diff changeset
23 * FFmpeg is distributed in the hope that it will be useful,
59
f40e091f7716 Add proper LGPL header.
diego
parents: 58
diff changeset
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
f40e091f7716 Add proper LGPL header.
diego
parents: 58
diff changeset
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
f40e091f7716 Add proper LGPL header.
diego
parents: 58
diff changeset
26 * Lesser General Public License for more details.
f40e091f7716 Add proper LGPL header.
diego
parents: 58
diff changeset
27 *
f40e091f7716 Add proper LGPL header.
diego
parents: 58
diff changeset
28 * You should have received a copy of the GNU Lesser General Public
116
d76a36742464 Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents: 59
diff changeset
29 * License along with FFmpeg; if not, write to the Free Software
59
f40e091f7716 Add proper LGPL header.
diego
parents: 58
diff changeset
30 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
45
31c84858af22 md5 support
michael
parents:
diff changeset
31 */
31c84858af22 md5 support
michael
parents:
diff changeset
32
31c84858af22 md5 support
michael
parents:
diff changeset
33 #include <string.h>
599
49da89abe282 Add necessary, remove unnecessary #includes.
diego
parents: 571
diff changeset
34 #include "bswap.h"
45
31c84858af22 md5 support
michael
parents:
diff changeset
35 #include "md5.h"
31c84858af22 md5 support
michael
parents:
diff changeset
36
31c84858af22 md5 support
michael
parents:
diff changeset
37 typedef struct AVMD5{
316
0846319fed73 cosmetic (order context variables like in sha1)
michael
parents: 314
diff changeset
38 uint64_t len;
45
31c84858af22 md5 support
michael
parents:
diff changeset
39 uint8_t block[64];
31c84858af22 md5 support
michael
parents:
diff changeset
40 uint32_t ABCD[4];
31c84858af22 md5 support
michael
parents:
diff changeset
41 } AVMD5;
31c84858af22 md5 support
michael
parents:
diff changeset
42
31c84858af22 md5 support
michael
parents:
diff changeset
43 const int av_md5_size= sizeof(AVMD5);
31c84858af22 md5 support
michael
parents:
diff changeset
44
31c84858af22 md5 support
michael
parents:
diff changeset
45 static const uint8_t S[4][4] = {
633
8c48a1b999a3 spelling/grammar/consistency review part I
diego
parents: 603
diff changeset
46 { 7, 12, 17, 22 }, /* round 1 */
8c48a1b999a3 spelling/grammar/consistency review part I
diego
parents: 603
diff changeset
47 { 5, 9, 14, 20 }, /* round 2 */
8c48a1b999a3 spelling/grammar/consistency review part I
diego
parents: 603
diff changeset
48 { 4, 11, 16, 23 }, /* round 3 */
8c48a1b999a3 spelling/grammar/consistency review part I
diego
parents: 603
diff changeset
49 { 6, 10, 15, 21 } /* round 4 */
45
31c84858af22 md5 support
michael
parents:
diff changeset
50 };
31c84858af22 md5 support
michael
parents:
diff changeset
51
318
a989eb26fcdd explain where the T table comes from
michael
parents: 316
diff changeset
52 static const uint32_t T[64] = { // T[i]= fabs(sin(i+1)<<32)
633
8c48a1b999a3 spelling/grammar/consistency review part I
diego
parents: 603
diff changeset
53 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, /* round 1 */
45
31c84858af22 md5 support
michael
parents:
diff changeset
54 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
31c84858af22 md5 support
michael
parents:
diff changeset
55 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
31c84858af22 md5 support
michael
parents:
diff changeset
56 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
31c84858af22 md5 support
michael
parents:
diff changeset
57
633
8c48a1b999a3 spelling/grammar/consistency review part I
diego
parents: 603
diff changeset
58 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, /* round 2 */
45
31c84858af22 md5 support
michael
parents:
diff changeset
59 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
31c84858af22 md5 support
michael
parents:
diff changeset
60 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
31c84858af22 md5 support
michael
parents:
diff changeset
61 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
31c84858af22 md5 support
michael
parents:
diff changeset
62
633
8c48a1b999a3 spelling/grammar/consistency review part I
diego
parents: 603
diff changeset
63 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, /* round 3 */
45
31c84858af22 md5 support
michael
parents:
diff changeset
64 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
31c84858af22 md5 support
michael
parents:
diff changeset
65 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
31c84858af22 md5 support
michael
parents:
diff changeset
66 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
31c84858af22 md5 support
michael
parents:
diff changeset
67
633
8c48a1b999a3 spelling/grammar/consistency review part I
diego
parents: 603
diff changeset
68 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, /* round 4 */
45
31c84858af22 md5 support
michael
parents:
diff changeset
69 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
31c84858af22 md5 support
michael
parents:
diff changeset
70 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
31c84858af22 md5 support
michael
parents:
diff changeset
71 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
31c84858af22 md5 support
michael
parents:
diff changeset
72 };
31c84858af22 md5 support
michael
parents:
diff changeset
73
31c84858af22 md5 support
michael
parents:
diff changeset
74 #define CORE(i, a, b, c, d) \
31c84858af22 md5 support
michael
parents:
diff changeset
75 t = S[i>>4][i&3];\
31c84858af22 md5 support
michael
parents:
diff changeset
76 a += T[i];\
31c84858af22 md5 support
michael
parents:
diff changeset
77 \
319
aac7ff53ef86 160 bytes smaller object file, ask gcc devels why
michael
parents: 318
diff changeset
78 if(i<32){\
aac7ff53ef86 160 bytes smaller object file, ask gcc devels why
michael
parents: 318
diff changeset
79 if(i<16) a += (d ^ (b&(c^d))) + X[ i &15 ];\
aac7ff53ef86 160 bytes smaller object file, ask gcc devels why
michael
parents: 318
diff changeset
80 else a += (c ^ (d&(c^b))) + X[ (1+5*i)&15 ];\
aac7ff53ef86 160 bytes smaller object file, ask gcc devels why
michael
parents: 318
diff changeset
81 }else{\
aac7ff53ef86 160 bytes smaller object file, ask gcc devels why
michael
parents: 318
diff changeset
82 if(i<48) a += (b^c^d) + X[ (5+3*i)&15 ];\
aac7ff53ef86 160 bytes smaller object file, ask gcc devels why
michael
parents: 318
diff changeset
83 else a += (c^(b|~d)) + X[ ( 7*i)&15 ];\
45
31c84858af22 md5 support
michael
parents:
diff changeset
84 }\
31c84858af22 md5 support
michael
parents:
diff changeset
85 a = b + (( a << t ) | ( a >> (32 - t) ));
31c84858af22 md5 support
michael
parents:
diff changeset
86
51
c6d76c080427 big endian fix
lu_zero
parents: 50
diff changeset
87 static void body(uint32_t ABCD[4], uint32_t X[16]){
53
01299a828431 fix endianess build in a better way
lu_zero
parents: 51
diff changeset
88
49
1a9c62b337e4 kill warnings
mru
parents: 46
diff changeset
89 int t;
339
8829032777d5 rename attribute_unused to av_unused and moves its declaration to common.h
benoit
parents: 319
diff changeset
90 int i av_unused;
45
31c84858af22 md5 support
michael
parents:
diff changeset
91 unsigned int a= ABCD[3];
31c84858af22 md5 support
michael
parents:
diff changeset
92 unsigned int b= ABCD[2];
31c84858af22 md5 support
michael
parents:
diff changeset
93 unsigned int c= ABCD[1];
31c84858af22 md5 support
michael
parents:
diff changeset
94 unsigned int d= ABCD[0];
31c84858af22 md5 support
michael
parents:
diff changeset
95
31c84858af22 md5 support
michael
parents:
diff changeset
96 #ifdef WORDS_BIGENDIAN
31c84858af22 md5 support
michael
parents:
diff changeset
97 for(i=0; i<16; i++)
31c84858af22 md5 support
michael
parents:
diff changeset
98 X[i]= bswap_32(X[i]);
31c84858af22 md5 support
michael
parents:
diff changeset
99 #endif
31c84858af22 md5 support
michael
parents:
diff changeset
100
603
880c6441f56a Change semantic of CONFIG_*, HAVE_* and ARCH_*.
aurel
parents: 599
diff changeset
101 #if CONFIG_SMALL
45
31c84858af22 md5 support
michael
parents:
diff changeset
102 for( i = 0; i < 64; i++ ){
31c84858af22 md5 support
michael
parents:
diff changeset
103 CORE(i,a,b,c,d)
31c84858af22 md5 support
michael
parents:
diff changeset
104 t=d; d=c; c=b; b=a; a=t;
31c84858af22 md5 support
michael
parents:
diff changeset
105 }
31c84858af22 md5 support
michael
parents:
diff changeset
106 #else
31c84858af22 md5 support
michael
parents:
diff changeset
107 #define CORE2(i) CORE(i,a,b,c,d) CORE((i+1),d,a,b,c) CORE((i+2),c,d,a,b) CORE((i+3),b,c,d,a)
31c84858af22 md5 support
michael
parents:
diff changeset
108 #define CORE4(i) CORE2(i) CORE2((i+4)) CORE2((i+8)) CORE2((i+12))
31c84858af22 md5 support
michael
parents:
diff changeset
109 CORE4(0) CORE4(16) CORE4(32) CORE4(48)
31c84858af22 md5 support
michael
parents:
diff changeset
110 #endif
31c84858af22 md5 support
michael
parents:
diff changeset
111
31c84858af22 md5 support
michael
parents:
diff changeset
112 ABCD[0] += d;
31c84858af22 md5 support
michael
parents:
diff changeset
113 ABCD[1] += c;
31c84858af22 md5 support
michael
parents:
diff changeset
114 ABCD[2] += b;
31c84858af22 md5 support
michael
parents:
diff changeset
115 ABCD[3] += a;
31c84858af22 md5 support
michael
parents:
diff changeset
116 }
31c84858af22 md5 support
michael
parents:
diff changeset
117
31c84858af22 md5 support
michael
parents:
diff changeset
118 void av_md5_init(AVMD5 *ctx){
31c84858af22 md5 support
michael
parents:
diff changeset
119 ctx->len = 0;
31c84858af22 md5 support
michael
parents:
diff changeset
120
31c84858af22 md5 support
michael
parents:
diff changeset
121 ctx->ABCD[0] = 0x10325476;
31c84858af22 md5 support
michael
parents:
diff changeset
122 ctx->ABCD[1] = 0x98badcfe;
31c84858af22 md5 support
michael
parents:
diff changeset
123 ctx->ABCD[2] = 0xefcdab89;
31c84858af22 md5 support
michael
parents:
diff changeset
124 ctx->ABCD[3] = 0x67452301;
31c84858af22 md5 support
michael
parents:
diff changeset
125 }
31c84858af22 md5 support
michael
parents:
diff changeset
126
31c84858af22 md5 support
michael
parents:
diff changeset
127 void av_md5_update(AVMD5 *ctx, const uint8_t *src, const int len){
312
93d504c22609 get rid of b_used variable (same size with CONFIG_SMALL)
michael
parents: 128
diff changeset
128 int i, j;
45
31c84858af22 md5 support
michael
parents:
diff changeset
129
312
93d504c22609 get rid of b_used variable (same size with CONFIG_SMALL)
michael
parents: 128
diff changeset
130 j= ctx->len & 63;
45
31c84858af22 md5 support
michael
parents:
diff changeset
131 ctx->len += len;
31c84858af22 md5 support
michael
parents:
diff changeset
132
31c84858af22 md5 support
michael
parents:
diff changeset
133 for( i = 0; i < len; i++ ){
312
93d504c22609 get rid of b_used variable (same size with CONFIG_SMALL)
michael
parents: 128
diff changeset
134 ctx->block[j++] = src[i];
93d504c22609 get rid of b_used variable (same size with CONFIG_SMALL)
michael
parents: 128
diff changeset
135 if( 64 == j ){
53
01299a828431 fix endianess build in a better way
lu_zero
parents: 51
diff changeset
136 body(ctx->ABCD, (uint32_t*) ctx->block);
312
93d504c22609 get rid of b_used variable (same size with CONFIG_SMALL)
michael
parents: 128
diff changeset
137 j = 0;
45
31c84858af22 md5 support
michael
parents:
diff changeset
138 }
31c84858af22 md5 support
michael
parents:
diff changeset
139 }
31c84858af22 md5 support
michael
parents:
diff changeset
140 }
31c84858af22 md5 support
michael
parents:
diff changeset
141
31c84858af22 md5 support
michael
parents:
diff changeset
142 void av_md5_final(AVMD5 *ctx, uint8_t *dst){
313
b4277e786617 borrow finalization algo from sha1 (100byte smaller)
michael
parents: 312
diff changeset
143 int i;
b4277e786617 borrow finalization algo from sha1 (100byte smaller)
michael
parents: 312
diff changeset
144 uint64_t finalcount= le2me_64(ctx->len<<3);
312
93d504c22609 get rid of b_used variable (same size with CONFIG_SMALL)
michael
parents: 128
diff changeset
145
313
b4277e786617 borrow finalization algo from sha1 (100byte smaller)
michael
parents: 312
diff changeset
146 av_md5_update(ctx, "\200", 1);
571
1d948bd9850c Fix generated md5, it was wrong for some input lengths.
michael
parents: 440
diff changeset
147 while((ctx->len & 63)!=56)
313
b4277e786617 borrow finalization algo from sha1 (100byte smaller)
michael
parents: 312
diff changeset
148 av_md5_update(ctx, "", 1);
45
31c84858af22 md5 support
michael
parents:
diff changeset
149
440
63e1f9c749dd fixing warning
michael
parents: 427
diff changeset
150 av_md5_update(ctx, (uint8_t*)&finalcount, 8);
45
31c84858af22 md5 support
michael
parents:
diff changeset
151
31c84858af22 md5 support
michael
parents:
diff changeset
152 for(i=0; i<4; i++)
31c84858af22 md5 support
michael
parents:
diff changeset
153 ((uint32_t*)dst)[i]= le2me_32(ctx->ABCD[3-i]);
31c84858af22 md5 support
michael
parents:
diff changeset
154 }
31c84858af22 md5 support
michael
parents:
diff changeset
155
31c84858af22 md5 support
michael
parents:
diff changeset
156 void av_md5_sum(uint8_t *dst, const uint8_t *src, const int len){
31c84858af22 md5 support
michael
parents:
diff changeset
157 AVMD5 ctx[1];
31c84858af22 md5 support
michael
parents:
diff changeset
158
31c84858af22 md5 support
michael
parents:
diff changeset
159 av_md5_init(ctx);
31c84858af22 md5 support
michael
parents:
diff changeset
160 av_md5_update(ctx, src, len);
31c84858af22 md5 support
michael
parents:
diff changeset
161 av_md5_final(ctx, dst);
31c84858af22 md5 support
michael
parents:
diff changeset
162 }
31c84858af22 md5 support
michael
parents:
diff changeset
163
31c84858af22 md5 support
michael
parents:
diff changeset
164 #ifdef TEST
31c84858af22 md5 support
michael
parents:
diff changeset
165 #include <stdio.h>
314
8b21778cb357 #undef printf under #ifdef TEST (needed for testing)
michael
parents: 313
diff changeset
166 #undef printf
427
e7192ff1857d Fix a couple of 'return type defaults to int' and 'control reaches end of
diego
parents: 404
diff changeset
167 int main(void){
45
31c84858af22 md5 support
michael
parents:
diff changeset
168 uint64_t md5val;
31c84858af22 md5 support
michael
parents:
diff changeset
169 int i;
31c84858af22 md5 support
michael
parents:
diff changeset
170 uint8_t in[1000];
31c84858af22 md5 support
michael
parents:
diff changeset
171
31c84858af22 md5 support
michael
parents:
diff changeset
172 for(i=0; i<1000; i++) in[i]= i*i;
128
d94fb7e6cb53 Replace most of the %lld and %llx by their (cleaner) PRI*64 counterparts.
diego
parents: 116
diff changeset
173 av_md5_sum( (uint8_t*)&md5val, in, 1000); printf("%"PRId64"\n", md5val);
d94fb7e6cb53 Replace most of the %lld and %llx by their (cleaner) PRI*64 counterparts.
diego
parents: 116
diff changeset
174 av_md5_sum( (uint8_t*)&md5val, in, 63); printf("%"PRId64"\n", md5val);
d94fb7e6cb53 Replace most of the %lld and %llx by their (cleaner) PRI*64 counterparts.
diego
parents: 116
diff changeset
175 av_md5_sum( (uint8_t*)&md5val, in, 64); printf("%"PRId64"\n", md5val);
d94fb7e6cb53 Replace most of the %lld and %llx by their (cleaner) PRI*64 counterparts.
diego
parents: 116
diff changeset
176 av_md5_sum( (uint8_t*)&md5val, in, 65); printf("%"PRId64"\n", md5val);
45
31c84858af22 md5 support
michael
parents:
diff changeset
177 for(i=0; i<1000; i++) in[i]= i % 127;
128
d94fb7e6cb53 Replace most of the %lld and %llx by their (cleaner) PRI*64 counterparts.
diego
parents: 116
diff changeset
178 av_md5_sum( (uint8_t*)&md5val, in, 999); printf("%"PRId64"\n", md5val);
427
e7192ff1857d Fix a couple of 'return type defaults to int' and 'control reaches end of
diego
parents: 404
diff changeset
179
e7192ff1857d Fix a couple of 'return type defaults to int' and 'control reaches end of
diego
parents: 404
diff changeset
180 return 0;
45
31c84858af22 md5 support
michael
parents:
diff changeset
181 }
31c84858af22 md5 support
michael
parents:
diff changeset
182 #endif