1 /* Generic CommonDigest wrappers to match the semantics of libmd. */
3 #include <dispatch/dispatch.h>
4 #include <os/assumes.h>
8 #include "commoncrypto.h"
10 #define CHUNK_SIZE (10 * 1024 * 1024)
13 Digest_End(CCDigestRef ctx
, char *buf
)
15 static const char hex
[] = "0123456789abcdef";
16 uint8_t digest
[32]; // SHA256 is the biggest
19 (void)os_assumes_zero(CCDigestFinal(ctx
, digest
));
20 length
= CCDigestOutputSize(ctx
);
21 os_assert(length
<= sizeof(digest
));
22 for (i
= 0; i
< length
; i
++) {
23 buf
[i
+i
] = hex
[digest
[i
] >> 4];
24 buf
[i
+i
+1] = hex
[digest
[i
] & 0x0f];
31 Digest_Data(CCDigestAlg algorithm
, const void *data
, size_t len
, char *buf
)
35 (void)os_assumes_zero(CCDigestInit(algorithm
, &ctx
));
36 (void)os_assumes_zero(CCDigestUpdate(&ctx
, data
, len
));
37 return Digest_End(&ctx
, buf
);
41 Digest_File(CCDigestAlg algorithm
, const char *filename
, char *buf
)
44 __block CCDigestCtx ctx
;
45 dispatch_queue_t queue
;
46 dispatch_semaphore_t sema
;
48 __block
int s_error
= 0;
49 __block
bool eof
= false;
52 /* dispatch_io_create_with_path requires an absolute path */
53 fd
= open(filename
, O_RDONLY
);
58 (void)fcntl(fd
, F_NOCACHE
, 1);
60 (void)os_assumes_zero(CCDigestInit(algorithm
, &ctx
));
62 queue
= dispatch_queue_create("com.apple.mtree.io", NULL
);
64 sema
= dispatch_semaphore_create(0);
67 io
= dispatch_io_create(DISPATCH_IO_STREAM
, fd
, queue
, ^(int error
) {
72 (void)dispatch_semaphore_signal(sema
);
75 for (chunk_offset
= 0; eof
== false && s_error
== 0; chunk_offset
+= CHUNK_SIZE
) {
76 dispatch_io_read(io
, chunk_offset
, CHUNK_SIZE
, queue
, ^(bool done
, dispatch_data_t data
, int error
) {
78 (void)dispatch_data_apply(data
, ^(__unused dispatch_data_t region
, __unused
size_t offset
, const void *buffer
, size_t size
) {
79 (void)os_assumes_zero(CCDigestUpdate(&ctx
, buffer
, size
));
89 eof
= (data
== dispatch_data_empty
);
90 dispatch_semaphore_signal(sema
);
93 dispatch_semaphore_wait(sema
, DISPATCH_TIME_FOREVER
);
95 dispatch_release(io
); // it will close on its own
97 (void)dispatch_semaphore_wait(sema
, DISPATCH_TIME_FOREVER
);
99 dispatch_release(queue
);
100 dispatch_release(sema
);
107 return Digest_End(&ctx
, buf
);