ObjFW  Check-in [631895440e]

Overview
Comment:Add OFSHA1Hash.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 631895440ef7e45f4db34389926469393b348774714989c0bb87711a016e4f45
User & Date: js on 2008-10-26 19:35:20
Other Links: manifest | tags
Context
2008-10-26
20:54
Return self when we have no return value. This allows nesting. check-in: 8ae4c59cd6 user: js tags: trunk
19:35
Add OFSHA1Hash. check-in: 631895440e user: js tags: trunk
17:48
OFMD5Hash improvements. check-in: 165c2c0b9d user: js tags: trunk
Changes

Modified configure.ac from [977f62d996] to [64e6ab3b03].

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
		OBJCFLAGS="$OBJSFLAGS -Wall -Werror -pipe -g"
		;;
esac

OBJCFLAGS="$OBJCFLAGS -fobjc-exceptions"

BUILDSYS_SHARED_LIB
AC_C_BIGENDIAN([AC_DEFINE(BIG_ENDIAN, 1, [Whether we are big endian])])

AC_CHECK_HEADER(objc/runtime.h,
	[AC_DEFINE(HAVE_OBJC_RUNTIME_H, 1, [Whether we have objc/runtime.h])])
AC_CHECK_LIB(objc, sel_get_name,
	[AC_DEFINE(HAVE_SEL_GET_NAME, 1, [Whether we have sel_get_name])])
AC_CHECK_LIB(objc, sel_getName,
	[AC_DEFINE(HAVE_SEL_GETNAME, 1, [Whether we have sel_getName])])







|







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
		OBJCFLAGS="$OBJSFLAGS -Wall -Werror -pipe -g"
		;;
esac

OBJCFLAGS="$OBJCFLAGS -fobjc-exceptions"

BUILDSYS_SHARED_LIB
AC_C_BIGENDIAN([AC_DEFINE(OF_BIG_ENDIAN, 1, [Whether we are big endian])])

AC_CHECK_HEADER(objc/runtime.h,
	[AC_DEFINE(HAVE_OBJC_RUNTIME_H, 1, [Whether we have objc/runtime.h])])
AC_CHECK_LIB(objc, sel_get_name,
	[AC_DEFINE(HAVE_SEL_GET_NAME, 1, [Whether we have sel_get_name])])
AC_CHECK_LIB(objc, sel_getName,
	[AC_DEFINE(HAVE_SEL_GETNAME, 1, [Whether we have sel_getName])])

Modified src/OFHashes.h from [4951f2110c] to [5de5b91012].

8
9
10
11
12
13
14



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
















 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#import <stdint.h>

#import "OFObject.h"




@interface OFMD5Hash: OFObject
{
	uint32_t buf[4];
	uint32_t bits[2];
	uint8_t	 in[64];

	BOOL	 calculated;
}

- init;
- (void)updateWithBuffer: (const uint8_t*)buf
		  ofSize: (size_t)size;
- (uint8_t*)digest;
@end























>
>
>











|
|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#import <stdint.h>

#import "OFObject.h"

#define MD5_DIGEST_SIZE	 16
#define SHA1_DIGEST_SIZE 20

@interface OFMD5Hash: OFObject
{
	uint32_t buf[4];
	uint32_t bits[2];
	uint8_t	 in[64];

	BOOL	 calculated;
}

- init;
- updateWithBuffer: (const uint8_t*)buf
	    ofSize: (size_t)size;
- (uint8_t*)digest;
@end

@interface OFSHA1Hash: OFObject
{
	uint32_t    state[5];
	uint64_t    count;
	uint8_t	    buffer[64];
	uint8_t	    digest[SHA1_DIGEST_SIZE];

	BOOL	 calculated;
}

- init;
- updateWithBuffer: (const uint8_t*)buf
	    ofSize: (size_t)size;
- (uint8_t*)digest;
@end

Modified src/OFHashes.m from [e568bcc89c] to [6a70fca031].

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34



35
36
37
38
39
40
41
#import "config.h"

#import <string.h>
#import <stdint.h>

#import "OFHashes.h"

#ifdef BIG_ENDIAN
inline void
bswap(uint8_t *buf, size_t len)
{
	uint32_t t;
	while (len--) {
		t = (uint32_t)((uint32_t)buf[3] << 8 | buf[2]) << 16 |
		    ((uint32_t)buf[1] << 8 | buf[0]);
		*(uint32_t*)buf = t;
		buf += 4;
	}
}
#else
#define bswap(buf, len)
#endif




/*******
 * MD5 *
 *******/

/* The four MD5 core functions - F1 is optimized somewhat */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)







|















>
>
>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#import "config.h"

#import <string.h>
#import <stdint.h>

#import "OFHashes.h"

#ifdef OF_BIG_ENDIAN
inline void
bswap(uint8_t *buf, size_t len)
{
	uint32_t t;
	while (len--) {
		t = (uint32_t)((uint32_t)buf[3] << 8 | buf[2]) << 16 |
		    ((uint32_t)buf[1] << 8 | buf[0]);
		*(uint32_t*)buf = t;
		buf += 4;
	}
}
#else
#define bswap(buf, len)
#endif

#define rol(val, bits) \
	(((val) << (bits)) | ((val) >> (32 - (bits))))

/*******
 * MD5 *
 *******/

/* The four MD5 core functions - F1 is optimized somewhat */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164

165
166
167

168
169
170
171
172
173

174
175
176
177

178
179
180

181
182
183
184
185
186
187
188
189

190
191
192
193
194
195


196
197
198
199
200
201
202

		calculated = NO;
	}

	return self;
}

- (void)updateWithBuffer: (const uint8_t*)buffer
		  ofSize: (size_t)size
{
	uint32_t t;

	if (calculated)
		return;
	if (size == 0)
		return;

	/* Update bitcount */
	t = bits[0];
	if ((bits[0] = t + ((uint32_t)size << 3)) < t)
		bits[1]++;		/* Carry from low to high */

	bits[1] += size >> 29;

	t = (t >> 3) & 0x3f;		/* Bytes already in shsInfo->data */


	/* Handle any leading odd-sized chunks */
	if (t) {
		uint8_t *p = (uint8_t*)in + t;

		t = 64 - t;

		if (size < t) {
			memcpy(p, buffer, size);
			return;
		}

		memcpy(p, buffer, t);
		bswap(in, 16);
		md5_transform(buf, (uint32_t*)in);

		buffer += t;
		size -= t;
	}

	/* Process data in 64-byte chunks */
	while (size >= 64) {
		memcpy(in, buffer, 64);
		bswap(in, 16);
		md5_transform(buf, (uint32_t*)in);

		buffer += 64;
		size -= 64;
	}

	/* Handle any remaining bytes of data. */
	memcpy(in, buffer, size);


}

- (uint8_t*)digest
{
	uint8_t	*p;
	size_t	count;








|
|




|

|




|
>


|
>






>


|

>



>









>






>
>







147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213

		calculated = NO;
	}

	return self;
}

- updateWithBuffer: (const uint8_t*)buffer
	    ofSize: (size_t)size
{
	uint32_t t;

	if (calculated)
		return self;
	if (size == 0)
		return self;

	/* Update bitcount */
	t = bits[0];
	if ((bits[0] = t + ((uint32_t)size << 3)) < t)
		/* Carry from low to high */
		bits[1]++;
	bits[1] += size >> 29;

	/* Bytes already in shsInfo->data */
	t = (t >> 3) & 0x3F;

	/* Handle any leading odd-sized chunks */
	if (t) {
		uint8_t *p = (uint8_t*)in + t;

		t = 64 - t;

		if (size < t) {
			memcpy(p, buffer, size);
			return self;
		}

		memcpy(p, buffer, t);
		bswap(in, 16);
		md5_transform(buf, (uint32_t*)in);

		buffer += t;
		size -= t;
	}

	/* Process data in 64-byte chunks */
	while (size >= 64) {
		memcpy(in, buffer, 64);
		bswap(in, 16);
		md5_transform(buf, (uint32_t*)in);

		buffer += 64;
		size -= 64;
	}

	/* Handle any remaining bytes of data. */
	memcpy(in, buffer, size);

	return self;
}

- (uint8_t*)digest
{
	uint8_t	*p;
	size_t	count;

214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
	*p++ = 0x80;

	/* Bytes of padding needed to make 64 bytes */
	count = 64 - 1 - count;

	/* Pad out to 56 mod 64 */
	if (count < 8) {
		/* Two lots of padding:  Pad the first block to 64 bytes */
		memset(p, 0, count);
		bswap(in, 16);
		md5_transform(buf, (uint32_t*)in);

		/* Now fill the next block with 56 bytes */
		memset(in, 0, 56);
	} else {







|







225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
	*p++ = 0x80;

	/* Bytes of padding needed to make 64 bytes */
	count = 64 - 1 - count;

	/* Pad out to 56 mod 64 */
	if (count < 8) {
		/* Two lots of padding: Pad the first block to 64 bytes */
		memset(p, 0, count);
		bswap(in, 16);
		md5_transform(buf, (uint32_t*)in);

		/* Now fill the next block with 56 bytes */
		memset(in, 0, 56);
	} else {
239
240
241
242
243
244
245
































































































































































	bswap((uint8_t*)buf, 4);

	calculated = YES;

	return (uint8_t*)buf;
}
@end







































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
	bswap((uint8_t*)buf, 4);

	calculated = YES;

	return (uint8_t*)buf;
}
@end

/********
 * SHA1 *
 ********/

/* blk0() and blk() perform the initial expand. */
#ifndef OF_BIG_ENDIAN
#define blk0(i)							\
	(block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) |	\
	    (rol(block->l[i], 8) & 0x00FF00FF))
#else
#define blk0(i) block->l[i]
#endif
#define blk(i) \
	(block->l[i & 15] = rol(block->l[(i + 13) & 15] ^	\
	    block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^	\
	    block->l[i & 15], 1))

/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
#define R0(v, w, x, y, z, i)						\
	z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5);	\
	w = rol(w, 30);
#define R1(v, w, x, y, z, i)						\
	z += ((w & (x ^ y)) ^ y) + blk(i) +  0x5A827999 + rol(v, 5);	\
	w = rol(w, 30);
#define R2(v, w, x, y, z, i)						\
	z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5);		\
	w = rol(w, 30);
#define R3(v, w, x, y, z, i)						  \
	z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
	w = rol(w, 30);
#define R4(v, w, x, y, z, i)						\
	z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5);		\
	w = rol(w, 30);

typedef union {
	uint8_t	 c[64];
	uint32_t l[16];
} sha1_c64l16_t;

inline void
sha1_transform(uint32_t state[5], const uint8_t buffer[64])
{
	uint32_t      a, b, c, d, e;
	uint8_t	      workspace[64];
	sha1_c64l16_t *block;

	block = (sha1_c64l16_t*)workspace;
	memcpy(block, buffer, 64);

	/* Copy state[] to working vars */
	a = state[0];
	b = state[1];
	c = state[2];
	d = state[3];
	e = state[4];

	/* 4 rounds of 20 operations each. Loop unrolled. */
	R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
	R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
	R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
	R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
	R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
	R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
	R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
	R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
	R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
	R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
	R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
	R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
	R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
	R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
	R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
	R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
	R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
	R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
	R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
	R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);

	/* Add the working vars back into state[] */
	state[0] += a;
	state[1] += b;
	state[2] += c;
	state[3] += d;
	state[4] += e;
}

@implementation OFSHA1Hash
- init
{
	if ((self = [super init])) {
		count = 0;
		state[0] = 0x67452301;
		state[1] = 0xEFCDAB89;
		state[2] = 0x98BADCFE;
		state[3] = 0x10325476;
		state[4] = 0xC3D2E1F0;
	}

	return self;
}

- updateWithBuffer: (const uint8_t*)buf
	    ofSize: (size_t)size
{
	size_t i, j;

	if (calculated)
		return self;
	if (size == 0)
		return self;

	j = (size_t)((count >> 3) & 63);
	count += (size << 3);

	if ((j + size) > 63) {
		memcpy(&buffer[j], buf, (i = 64 - j));

		sha1_transform(state, buffer);

		for (; i + 63 < size; i += 64)
			sha1_transform(state, &buf[i]);

		j = 0;
	} else
		i = 0;

	memcpy(&buffer[j], &buf[i], size - i);

	return self;
}

- (uint8_t*)digest
{
	size_t i;
	uint8_t finalcount[8];

	if (calculated)
		return digest;

	for (i = 0; i < 8; i++)
		/* Endian independent */
		finalcount[i] = (uint8_t)((count >> ((7 - (i & 7)) * 8)) & 255);
	[self updateWithBuffer: (const uint8_t*)"\200"
			ofSize: 1];

	while ((count & 504) != 448)
		[self updateWithBuffer: (const uint8_t*)"\0"
				ofSize: 1];
	/* Should cause a sha1_transform() */
	[self updateWithBuffer: finalcount
			ofSize: 8]; 

	for (i = 0; i < SHA1_DIGEST_SIZE; i++)
		digest[i] = (uint8_t)((state[i >> 2] >>
		    ((3 - (i & 3)) * 8)) & 255);

	return digest;
}
@end

Modified tests/OFHashes/OFHashes.m from [23304eed47] to [2a964a3068].

11
12
13
14
15
16
17
18
19



20
21
22
23
24
25
26
27

28
29
30
31
32
33
34
35
36


37
38
39
40
41
42
43
44
45
46








47
48
49

#import <stdio.h>
#import <string.h>

#import "OFHashes.h"
#import "OFFile.h"

const uint8_t testfile_md5[16] =
    "\x00\x8B\x9D\x1B\x58\xDF\xF8\xFE\xEE\xF3\xAE\x8D\xBB\x68\x2D\x38";




int
main()
{
	uint8_t buf[64];
	size_t	len;

	OFMD5Hash *md5 = [OFMD5Hash new];

	OFFile *f = [OFFile newWithPath: "testfile"
				andMode: "r"];

	while (![f atEndOfFile]) {
		len = [f readIntoBuffer: buf
			       withSize: 1
			      andNItems: 64];
		[md5 updateWithBuffer: buf
			       ofSize: len];


	}
	[f free];

	if (!memcmp([md5 digest], testfile_md5, 16))
		puts("Correct MD5 sum calculated!");
	else {
		puts("MD5 SUM MISMATCH!!");
		return 1;
	}
	[md5 free];









	return 0;
}







|

>
>
>







|
>

|







>
>



|






>
>
>
>
>
>
>
>



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

#import <stdio.h>
#import <string.h>

#import "OFHashes.h"
#import "OFFile.h"

const uint8_t testfile_md5[MD5_DIGEST_SIZE] =
    "\x00\x8B\x9D\x1B\x58\xDF\xF8\xFE\xEE\xF3\xAE\x8D\xBB\x68\x2D\x38";
const uint8_t testfile_sha1[SHA1_DIGEST_SIZE] =
    "\xC9\x9A\xB8\x7E\x1E\xC8\xEC\x65\xD5\xEB\xE4\x2E\x0D\xA6\x80\x96\xF5"
    "\x94\xE7\x17";

int
main()
{
	uint8_t buf[64];
	size_t	len;

	OFMD5Hash  *md5  = [OFMD5Hash new];
	OFSHA1Hash *sha1 = [OFSHA1Hash new];
	OFFile *f = [OFFile newWithPath: "testfile"
				andMode: "rb"];

	while (![f atEndOfFile]) {
		len = [f readIntoBuffer: buf
			       withSize: 1
			      andNItems: 64];
		[md5 updateWithBuffer: buf
			       ofSize: len];
		[sha1 updateWithBuffer: buf
				ofSize: len];
	}
	[f free];

	if (!memcmp([md5 digest], testfile_md5, MD5_DIGEST_SIZE))
		puts("Correct MD5 sum calculated!");
	else {
		puts("MD5 SUM MISMATCH!!");
		return 1;
	}
	[md5 free];

	if (!memcmp([sha1 digest], testfile_sha1, SHA1_DIGEST_SIZE))
		puts("Correct SHA1 sum calculated!");
	else {
		puts("SHA1 SUM MISMATCH!!");
		return 1;
	}
	[sha1 free];

	return 0;
}