summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chksum.c563
1 files changed, 211 insertions, 352 deletions
diff --git a/chksum.c b/chksum.c
index d3381713..1058b247 100644
--- a/chksum.c
+++ b/chksum.c
@@ -51,50 +51,6 @@
static val sha256_ctx_s, md5_ctx_s;
static struct cobj_class *sha256_ctx_cls, *md5_ctx_cls;
-static void sha256_stream_impl(val stream, val nbytes, unsigned char *hash,
- val self)
-{
- SHA256_t s256;
- val buf = iobuf_get();
- val bfsz = length_buf(buf);
- SHA256_init(&s256);
-
- if (null_or_missing_p(nbytes)) {
- for (;;) {
- val read = fill_buf(buf, zero, stream);
- cnum rd = c_num(read, self);
-
- if (!rd)
- break;
-
- SHA256_update(&s256, buf->b.data, rd);
- }
- } else {
- while (ge(nbytes, bfsz)) {
- val read = fill_buf(buf, zero, stream);
- cnum rd = c_num(read, self);
-
- if (zerop(read))
- break;
-
- SHA256_update(&s256, buf->b.data, rd);
- nbytes = minus(nbytes, read);
- }
-
- buf_set_length(buf, nbytes, nil);
-
- {
- val read = fill_buf(buf, zero, stream);
- cnum rd = c_num(read, self);
- if (rd)
- SHA256_update(&s256, buf->b.data, rd);
- }
- }
-
- SHA256_final(&s256, hash);
- iobuf_put(buf);
-}
-
static val chksum_ensure_buf(val self, val buf_in,
val len, unsigned char **phash,
val hash_name)
@@ -111,139 +67,220 @@ static val chksum_ensure_buf(val self, val buf_in,
}
}
-val sha256_stream(val stream, val nbytes, val buf_in)
-{
- val self = lit("sha256-stream");
- unsigned char *hash;
- val buf = chksum_ensure_buf(self, buf_in, num_fast(SHA256_DIGEST_LENGTH),
- &hash, lit("SHA-256"));
- sha256_stream_impl(stream, nbytes, hash, self);
- return buf;
-}
-
-static void sha256_szmax_upd(SHA256_t *ps256, mem_t *data, ucnum len)
-{
- const size_t szmax = convert(size_t, -1) / 4 + 1;
- while (len >= szmax) {
- SHA256_update(ps256, data, szmax);
- data += szmax;
- len -= szmax;
+#define chksum_impl(nameroot, ctx_type, \
+ hash_name, digest_len, chksum_init, \
+ chksum_update, chksum_final) \
+ \
+ static void nameroot ## _stream_impl(val stream, \
+ val nbytes, \
+ unsigned char *hash, \
+ val self) \
+ { \
+ ctx_type ctx; \
+ val buf = iobuf_get(); \
+ val bfsz = length_buf(buf); \
+ chksum_init(&ctx); \
+ \
+ if (null_or_missing_p(nbytes)) { \
+ for (;;) { \
+ val read = fill_buf(buf, zero, stream); \
+ cnum rd = c_num(read, self); \
+ \
+ if (!rd) \
+ break; \
+ \
+ chksum_update(&ctx, buf->b.data, rd); \
+ } \
+ } else { \
+ while (ge(nbytes, bfsz)) { \
+ val read = fill_buf(buf, zero, stream); \
+ cnum rd = c_num(read, self); \
+ \
+ if (zerop(read)) \
+ break; \
+ \
+ chksum_update(&ctx, buf->b.data, rd); \
+ nbytes = minus(nbytes, read); \
+ } \
+ \
+ buf_set_length(buf, nbytes, nil); \
+ \
+ { \
+ val read = fill_buf(buf, zero, stream); \
+ cnum rd = c_num(read, self); \
+ if (rd) \
+ chksum_update(&ctx, buf->b.data, rd); \
+ } \
+ } \
+ \
+ chksum_final(&ctx, hash); \
+ iobuf_put(buf); \
+ } \
+ \
+ val nameroot ## _stream(val stream, val nbytes, val buf_in) \
+ { \
+ val self = lit(#nameroot "-stream"); \
+ unsigned char *hash; \
+ val buf = chksum_ensure_buf(self, buf_in, \
+ num_fast(digest_len), \
+ &hash, lit(hash_name)); \
+ nameroot ## _stream_impl(stream, nbytes, hash, self); \
+ return buf; \
+ } \
+ \
+ static void nameroot ## _szmax_upd(ctx_type *pctx, \
+ mem_t *data, ucnum len) \
+ { \
+ const size_t szmax = convert(size_t, -1) / 4 + 1; \
+ while (len >= szmax) { \
+ chksum_update(pctx, data, szmax); \
+ data += szmax; \
+ len -= szmax; \
+ } \
+ if (len > 0) \
+ chksum_update(pctx, data, len); \
+ } \
+ \
+ static void nameroot ## _buf(val buf, unsigned char *hash, \
+ val self) \
+ { \
+ ctx_type ctx; \
+ chksum_init(&ctx); \
+ nameroot ## _szmax_upd(&ctx, buf->b.data, \
+ c_unum(buf->b.len, self)); \
+ chksum_final(&ctx, hash); \
+ } \
+ \
+ static void nameroot ## _str(val str, unsigned char *hash, \
+ val self) \
+ { \
+ char *s = utf8_dup_to(c_str(str, self)); \
+ ctx_type ctx; \
+ chksum_init(&ctx); \
+ chksum_update(&ctx, coerce(const unsigned char *, s), \
+ strlen(s)); \
+ free(s); \
+ chksum_final(&ctx, hash); \
+ } \
+ \
+ val nameroot(val obj, val buf_in) \
+ { \
+ val self = lit(#nameroot); \
+ unsigned char *hash; \
+ val buf = chksum_ensure_buf(self, buf_in, \
+ num_fast(digest_len), \
+ &hash, lit(hash_name)); \
+ switch (type(obj)) { \
+ case STR: \
+ case LSTR: \
+ case LIT: \
+ nameroot ## _str(obj, hash, self); \
+ return buf; \
+ case BUF: \
+ nameroot ## _buf(obj, hash, self); \
+ return buf; \
+ default: \
+ uw_throwf(error_s, \
+ lit("~a: cannot hash ~s, " \
+ "only buffer and strings"), \
+ self, obj, nao); \
+ } \
+ } \
+ \
+ static struct cobj_ops nameroot ## _ops = \
+ cobj_ops_init(cobj_equal_handle_op, \
+ cobj_print_op, \
+ cobj_destroy_free_op, \
+ cobj_mark_op, \
+ cobj_handle_hash_op); \
+ \
+ val nameroot ## _begin(void) \
+ { \
+ ctx_type *pctx = coerce(ctx_type *, \
+ chk_malloc(sizeof *pctx)); \
+ chksum_init(pctx); \
+ return cobj(coerce(mem_t *, pctx), \
+ nameroot ## _ctx_cls, &nameroot ## _ops); \
+ } \
+ \
+ static int nameroot ## _utf8_byte_callback(int b, \
+ mem_t *ctx) \
+ { \
+ ctx_type *pctx = coerce(ctx_type *, ctx); \
+ unsigned char uc = b; \
+ chksum_update(pctx, &uc, 1); \
+ return 1; \
+ } \
+ \
+ val nameroot ## _hash(val ctx, val obj) \
+ { \
+ val self = lit(#nameroot "-hash"); \
+ ctx_type *pctx = coerce(ctx_type *, \
+ cobj_handle(self, ctx, \
+ nameroot ## \
+ _ctx_cls)); \
+ switch (type(obj)) { \
+ case STR: \
+ case LSTR: \
+ case LIT: \
+ { \
+ char *str = utf8_dup_to(c_str(obj, self)); \
+ chksum_update(pctx, \
+ coerce(const unsigned char *, str), \
+ strlen(str)); \
+ free(str); \
+ } \
+ break; \
+ case BUF: \
+ nameroot ## _szmax_upd(pctx, obj->b.data, \
+ c_unum(obj->b.len, self)); \
+ break; \
+ case CHR: \
+ utf8_encode(c_ch(obj), \
+ nameroot ## _utf8_byte_callback, \
+ coerce(mem_t *, pctx)); \
+ break; \
+ case NUM: \
+ { \
+ cnum n = c_num(obj, self); \
+ unsigned char uc = n; \
+ if (n < 0 || n > 255) \
+ uw_throwf(error_s, \
+ lit("~a: byte value ~s out of range"), \
+ self, obj, nao); \
+ chksum_update(pctx, &uc, 1); \
+ } \
+ break; \
+ default: \
+ uw_throwf(error_s, lit("~a: cannot hash ~s, " \
+ "only buffer and strings"), \
+ self, obj, nao); \
+ } \
+ \
+ return obj; \
+ } \
+ \
+ val nameroot ## _end(val ctx, val buf_in) \
+ { \
+ val self = lit(#nameroot "-end"); \
+ unsigned char *hash; \
+ ctx_type *pctx = coerce(ctx_type *, \
+ cobj_handle(self, ctx, \
+ nameroot ## \
+ _ctx_cls)); \
+ val buf = chksum_ensure_buf(self, buf_in, \
+ num_fast(digest_len), \
+ &hash, lit(hash_name)); \
+ chksum_final(pctx, hash); \
+ chksum_init(pctx); \
+ return buf; \
}
- if (len > 0)
- SHA256_update(ps256, data, len);
-}
-static void sha256_buf(val buf, unsigned char *hash, val self)
-{
- SHA256_t s256;
- SHA256_init(&s256);
- sha256_szmax_upd(&s256, buf->b.data, c_unum(buf->b.len, self));
- SHA256_final(&s256, hash);
-}
-
-static void sha256_str(val str, unsigned char *hash, val self)
-{
- char *s = utf8_dup_to(c_str(str, self));
- SHA256_t s256;
- SHA256_init(&s256);
- SHA256_update(&s256, coerce(const unsigned char *, s), strlen(s));
- free(s);
- SHA256_final(&s256, hash);
-}
-
-val sha256(val obj, val buf_in)
-{
- val self = lit("sha256");
- unsigned char *hash;
- val buf = chksum_ensure_buf(self, buf_in, num_fast(SHA256_DIGEST_LENGTH),
- &hash, lit("SHA-256"));
-
- switch (type(obj)) {
- case STR:
- case LSTR:
- case LIT:
- sha256_str(obj, hash, self);
- return buf;
- case BUF:
- sha256_buf(obj, hash, self);
- return buf;
- default:
- uw_throwf(error_s, lit("~a: cannot hash ~s, only buffer and strings"),
- self, obj, nao);
- }
-}
-
-static struct cobj_ops sha256_ops = cobj_ops_init(cobj_equal_handle_op,
- cobj_print_op,
- cobj_destroy_free_op,
- cobj_mark_op,
- cobj_handle_hash_op);
-val sha256_begin(void)
-{
- SHA256_t *ps256 = coerce(SHA256_t *, chk_malloc(sizeof *ps256));
- SHA256_init(ps256);
- return cobj(coerce(mem_t *, ps256), sha256_ctx_cls, &sha256_ops);
-}
-
-static int sha256_utf8_byte_callback(int b, mem_t *ctx)
-{
- SHA256_t *ps256 = coerce(SHA256_t *, ctx);
- unsigned char uc = b;
- SHA256_update(ps256, &uc, 1);
- return 1;
-}
+chksum_impl(sha256, SHA256_t, "SHA-256", SHA256_DIGEST_LENGTH,
+ SHA256_init, SHA256_update, SHA256_final);
-val sha256_hash(val ctx, val obj)
-{
- val self = lit("sha256-hash");
- SHA256_t *ps256 = coerce(SHA256_t *, cobj_handle(self, ctx, sha256_ctx_cls));
-
- switch (type(obj)) {
- case STR:
- case LSTR:
- case LIT:
- {
- char *str = utf8_dup_to(c_str(obj, self));
- SHA256_update(ps256, coerce(const unsigned char *, str), strlen(str));
- free(str);
- }
- break;
- case BUF:
- sha256_szmax_upd(ps256, obj->b.data, c_unum(obj->b.len, self));
- break;
- case CHR:
- utf8_encode(c_ch(obj), sha256_utf8_byte_callback, coerce(mem_t *, ps256));
- break;
- case NUM:
- {
- cnum n = c_num(obj, self);
- unsigned char uc = n;
- if (n < 0 || n > 255)
- uw_throwf(error_s, lit("~a: byte value ~s out of range"),
- self, obj, nao);
- SHA256_update(ps256, &uc, 1);
- }
- break;
- default:
- uw_throwf(error_s, lit("~a: cannot hash ~s, only buffer and strings"),
- self, obj, nao);
- }
-
- return obj;
-}
-
-val sha256_end(val ctx, val buf_in)
-{
- val self = lit("sha256-end");
- unsigned char *hash;
- SHA256_t *ps256 = coerce(SHA256_t *, cobj_handle(self, ctx, sha256_ctx_cls));
- val buf = chksum_ensure_buf(self, buf_in, num_fast(SHA256_DIGEST_LENGTH),
- &hash, lit("SHA-256"));
-
- SHA256_final(ps256, hash);
- SHA256_init(ps256);
- return buf;
-}
+chksum_impl(md5, MD5_t, "MD5", MD5_DIGEST_LENGTH,
+ MD5_init, MD5_update, MD5_final);
val crc32_stream(val stream, val nbytes, val init)
{
@@ -331,184 +368,6 @@ static val crc32(val obj, val init)
}
}
-static void md5_stream_impl(val stream, val nbytes, unsigned char *hash,
- val self)
-{
- MD5_t md5;
- val buf = iobuf_get();
- val bfsz = length_buf(buf);
- MD5_init(&md5);
-
- if (null_or_missing_p(nbytes)) {
- for (;;) {
- val read = fill_buf(buf, zero, stream);
- cnum rd = c_num(read, self);
-
- if (!rd)
- break;
-
- MD5_update(&md5, buf->b.data, rd);
- }
- } else {
- while (ge(nbytes, bfsz)) {
- val read = fill_buf(buf, zero, stream);
- cnum rd = c_num(read, self);
-
- if (zerop(read))
- break;
-
- MD5_update(&md5, buf->b.data, rd);
- nbytes = minus(nbytes, read);
- }
-
- buf_set_length(buf, nbytes, nil);
-
- {
- val read = fill_buf(buf, zero, stream);
- cnum rd = c_num(read, self);
- if (rd)
- MD5_update(&md5, buf->b.data, rd);
- }
- }
-
- MD5_final(&md5, hash);
- iobuf_put(buf);
-}
-
-val md5_stream(val stream, val nbytes, val buf_in)
-{
- val self = lit("md5-stream");
- unsigned char *hash;
- val buf = chksum_ensure_buf(self, buf_in, num_fast(MD5_DIGEST_LENGTH),
- &hash, lit("MD5"));
- md5_stream_impl(stream, nbytes, hash, self);
- return buf;
-}
-
-static void md5_szmax_upd(MD5_t *pmd5, mem_t *data, ucnum len)
-{
- const size_t szmax = convert(size_t, -1) / 4 + 1;
- while (len >= szmax) {
- MD5_update(pmd5, data, szmax);
- data += szmax;
- len -= szmax;
- }
- if (len > 0)
- MD5_update(pmd5, data, len);
-}
-
-static void md5_buf(val buf, unsigned char *hash, val self)
-{
- MD5_t md5;
- MD5_init(&md5);
- md5_szmax_upd(&md5, buf->b.data, c_unum(buf->b.len, self));
- MD5_final(&md5, hash);
-}
-
-static void md5_str(val str, unsigned char *hash, val self)
-{
- char *s = utf8_dup_to(c_str(str, self));
- MD5_t md5;
- MD5_init(&md5);
- MD5_update(&md5, coerce(const unsigned char *, s), strlen(s));
- free(s);
- MD5_final(&md5, hash);
-}
-
-val md5(val obj, val buf_in)
-{
- val self = lit("md5");
- unsigned char *hash;
- val buf = chksum_ensure_buf(self, buf_in, num_fast(MD5_DIGEST_LENGTH),
- &hash, lit("MD5"));
-
- switch (type(obj)) {
- case STR:
- case LSTR:
- case LIT:
- md5_str(obj, hash, self);
- return buf;
- case BUF:
- md5_buf(obj, hash, self);
- return buf;
- default:
- uw_throwf(error_s, lit("~a: cannot hash ~s, only buffer and strings"),
- self, obj, nao);
- }
-}
-
-static struct cobj_ops md5_ops = cobj_ops_init(cobj_equal_handle_op,
- cobj_print_op,
- cobj_destroy_free_op,
- cobj_mark_op,
- cobj_handle_hash_op);
-val md5_begin(void)
-{
- MD5_t *pmd5 = coerce(MD5_t *, chk_malloc(sizeof *pmd5));
- MD5_init(pmd5);
- return cobj(coerce(mem_t *, pmd5), md5_ctx_cls, &md5_ops);
-}
-
-static int md5_utf8_byte_callback(int b, mem_t *ctx)
-{
- MD5_t *ps256 = coerce(MD5_t *, ctx);
- unsigned char uc = b;
- MD5_update(ps256, &uc, 1);
- return 1;
-}
-
-val md5_hash(val ctx, val obj)
-{
- val self = lit("md5-hash");
- MD5_t *pmd5 = coerce(MD5_t *, cobj_handle(self, ctx, md5_ctx_cls));
-
- switch (type(obj)) {
- case STR:
- case LSTR:
- case LIT:
- {
- char *str = utf8_dup_to(c_str(obj, self));
- MD5_update(pmd5, coerce(const unsigned char *, str), strlen(str));
- free(str);
- }
- break;
- case BUF:
- md5_szmax_upd(pmd5, obj->b.data, c_unum(obj->b.len, self));
- break;
- case CHR:
- utf8_encode(c_ch(obj), md5_utf8_byte_callback, coerce(mem_t *, pmd5));
- break;
- case NUM:
- {
- cnum n = c_num(obj, self);
- unsigned char uc = n;
- if (n < 0 || n > 255)
- uw_throwf(error_s, lit("~a: byte value ~s out of range"),
- self, obj, nao);
- MD5_update(pmd5, &uc, 1);
- }
- break;
- default:
- uw_throwf(error_s, lit("~a: cannot hash ~s, only buffer and strings"),
- self, obj, nao);
- }
-
- return obj;
-}
-
-val md5_end(val ctx, val buf_in)
-{
- val self = lit("md5-end");
- unsigned char *hash;
- MD5_t *pmd5 = coerce(MD5_t *, cobj_handle(self, ctx, md5_ctx_cls));
- val buf = chksum_ensure_buf(self, buf_in, num_fast(MD5_DIGEST_LENGTH),
- &hash, lit("SHA-256"));
-
- MD5_final(pmd5, hash);
- MD5_init(pmd5);
- return buf;
-}
-
void chksum_init(void)
{
sha256_ctx_s = intern(lit("sha256-ctx"), user_package);