From e97fcce078008f3e65e785604dedf9fef77b5b53 Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Wed, 18 May 2016 14:33:58 +0100 Subject: [PATCH] added other shaX family functions --- bc/scripts/bif_common.tab | 47 +++-- core/bif_crypto.c | 375 ++++++++++++++------------------------ core/bif_hash.c | 191 ------------------- 3 files changed, 172 insertions(+), 441 deletions(-) diff --git a/bc/scripts/bif_common.tab b/bc/scripts/bif_common.tab index 747e629..49cc613 100644 --- a/bc/scripts/bif_common.tab +++ b/bc/scripts/bif_common.tab @@ -198,11 +198,6 @@ erlang:phash(Term,Range) cbif_phash2 erlang:phash2(Term) cbif_phash2_1 erlang:phash2(Term,Range) cbif_phash2_2 -erlang:md5(Data) cbif_md5_1 -erlang:md5_init() cbif_md5_init0 -erlang:md5_update(Ctx,IoData) cbif_md5_update2 -erlang:md5_final(Ctx) cbif_md5_final1 - erlang:crc32(Old,Data) cbif_crc32_2 erlang:crc32_combine(Fst,Sec,Sz) cbif_crc32_combine3 erlang:adler32(Old,Data) cbif_adler32_2 @@ -387,21 +382,45 @@ maps:update(Key,Value,Map1) cbif_update3 maps:values(Map) cbif_values1 #bif_crypto.c -crypto:md5(Data) cbif_md5_1 -crypto:md5_init() cbif_md5_init0 -crypto:md5_update(Ctx,IoData) cbif_md5_update2 +crypto:md5(Data) cbif_md5_1 +crypto:md5_init() cbif_md5_init0 +crypto:md5_update(Ctx,Data) cbif_md5_update2 crypto:md5_final(Ctx) cbif_md5_final1 +crypto:md5_mac_n(Key,Data,Size) cbif_md5_mac_n3 -crypto:sha(Data) cbif_sha1 -crypto:sha_init() cbif_sha_init0 -crypto:sha_update(Ctx,Data) cbif_sha_update2 -crypto:sha_final(Ctx) cbif_sha_final1 +erlang:md5(Data) cbif_md5_1 +erlang:md5_init() cbif_md5_init0 +erlang:md5_update(Ctx,Data) cbif_md5_update2 +erlang:md5_final(Ctx) cbif_md5_final1 -crypto:md5_mac_n(Key,Data,Size) cbif_md5_mac_n3 -crypto:sha_mac_n(Key,Data,Size) cbif_sha_mac_n3 +crypto:sha(Data) cbif_sha1_1 +crypto:sha_init() cbif_sha1_init0 +crypto:sha_update(Ctx,Data) cbif_sha1_update2 +crypto:sha_final(Ctx) cbif_sha1_final1 +crypto:sha_mac_n(Key,Data,Size) cbif_sha1_mac_n3 + +crypto:sha224(Data) cbif_sha224_1 +crypto:sha224_init() cbif_sha224_init0 +crypto:sha224_update(Ctx,Data) cbif_sha224_update2 +crypto:sha224_final(Ctx) cbif_sha224_final1 crypto:sha224_mac_n(Key,Data,Size) cbif_sha224_mac_n3 + +crypto:sha256(Data) cbif_sha256_1 +crypto:sha256_init() cbif_sha256_init0 +crypto:sha256_update(Ctx,Data) cbif_sha256_update2 +crypto:sha256_final(Ctx) cbif_sha256_final1 crypto:sha256_mac_n(Key,Data,Size) cbif_sha256_mac_n3 + +crypto:sha384(Data) cbif_sha384_1 +crypto:sha384_init() cbif_sha384_init0 +crypto:sha384_update(Ctx,Data) cbif_sha384_update2 +crypto:sha384_final(Ctx) cbif_sha384_final1 crypto:sha384_mac_n(Key,Data,Size) cbif_sha384_mac_n3 + +crypto:sha512(Data) cbif_sha512_1 +crypto:sha512_init() cbif_sha512_init0 +crypto:sha512_update(Ctx,Data) cbif_sha512_update2 +crypto:sha512_final(Ctx) cbif_sha512_final1 crypto:sha512_mac_n(Key,Data,Size) cbif_sha512_mac_n3 crypto:aes_cbc_crypt(Key,IVec,Data,Dir) cbif_aes_cbc_crypt4 diff --git a/core/bif_crypto.c b/core/bif_crypto.c index 0745db6..c80130f 100644 --- a/core/bif_crypto.c +++ b/core/bif_crypto.c @@ -33,244 +33,147 @@ #include "bif_impl.h" -term_t cbif_sha1(proc_t *proc, term_t *regs) -{ - term_t Data = regs[0]; - - if (!is_boxed_binary(Data) && !is_list(Data)) - badarg(Data); - - int sz = iolist_size(Data); - if (sz < 0) - badarg(Data); - assert(sz <= 65536); //TODO: use heap_tmp_buf for larger Data - uint8_t buf[sz]; - iolist_flatten(Data, buf); - - struct sha1_ctx ctx; - sha1_init(&ctx); - sha1_update(&ctx, sz, buf); - - uint8_t *ptr; - term_t bin = heap_make_bin(&proc->hp, SHA1_DIGEST_SIZE, &ptr); - sha1_digest(&ctx, SHA1_DIGEST_SIZE, ptr); - - return bin; -} - -term_t cbif_sha_init0(proc_t *proc, term_t *regs) -{ - struct sha1_ctx *ctx; - term_t bin = heap_make_bin(&proc->hp, sizeof(*ctx), (uint8_t **)&ctx); - sha1_init(ctx); - return bin; +#define DIGEST(l, u) \ +term_t cbif_##l##_1(proc_t *proc, term_t *regs) \ +{ \ + term_t Data = regs[0]; \ + \ + if (!is_boxed_binary(Data) && !is_list(Data)) \ + badarg(Data); \ + \ + int sz = iolist_size(Data); \ + if (sz < 0) \ + badarg(Data); \ + assert(sz <= 65536); /* TODO: use heap_tmp_buf for larger Data */ \ + uint8_t buf[sz]; \ + iolist_flatten(Data, buf); \ + \ + struct l##_ctx ctx; \ + l##_init(&ctx); \ + l##_update(&ctx, sz, buf); \ + \ + uint8_t *ptr; \ + term_t bin = heap_make_bin(&proc->hp, u##_DIGEST_SIZE, &ptr); \ + l##_digest(&ctx, u##_DIGEST_SIZE, ptr); \ + \ + return bin; \ +} \ + \ +term_t cbif_##l##_init0(proc_t *proc, term_t *regs) \ +{ \ + struct l##_ctx *ctx; \ + term_t bin = heap_make_bin(&proc->hp, sizeof(*ctx), (uint8_t **)&ctx); \ + l##_init(ctx); \ + return bin; \ +} \ + \ +term_t cbif_##l##_update2(proc_t *proc, term_t *regs) \ +{ \ + term_t Context = regs[0]; \ + term_t Data = regs[1]; \ + \ + if (!is_boxed_binary(Context)) \ + badarg(Context); \ + \ + bits_t bs, dst; \ + bits_get_real(peel_boxed(Context), &bs); \ + if (bs.ends -bs.starts != sizeof(struct l##_ctx) *8) \ + badarg(Context); \ + \ + struct l##_ctx ctx; \ + bits_init_buf((uint8_t *)&ctx, sizeof(ctx), &dst); \ + bits_copy(&bs, &dst); \ + \ + if (!is_boxed_binary(Data) && !is_list(Data)) \ + badarg(Data); \ + \ + int sz = iolist_size(Data); \ + if (sz < 0) \ + badarg(Data); \ + assert(sz <= 65536); /* TODO: use heap_tmp_buf for larger Data */ \ + uint8_t buf[sz]; \ + iolist_flatten(Data, buf); \ + \ + l##_update(&ctx, sz, buf); \ + \ + uint8_t *ptr; \ + term_t bin = heap_make_bin(&proc->hp, sizeof(ctx), &ptr); \ + memcpy(ptr, &ctx, sizeof(ctx)); \ + \ + return bin; \ +} \ + \ +term_t cbif_##l##_final1(proc_t *proc, term_t *regs) \ +{ \ + term_t Context = regs[0]; \ + \ + if (!is_boxed_binary(Context)) \ + badarg(Context); \ + \ + bits_t bs, dst; \ + bits_get_real(peel_boxed(Context), &bs); \ + if (bs.ends -bs.starts != sizeof(struct l##_ctx) *8) \ + badarg(Context); \ + \ + struct l##_ctx ctx; \ + bits_init_buf((uint8_t *)&ctx, sizeof(ctx), &dst); \ + bits_copy(&bs, &dst); \ + \ + uint8_t *ptr; \ + term_t bin = heap_make_bin(&proc->hp, u##_DIGEST_SIZE, &ptr); \ + l##_digest(&ctx, u##_DIGEST_SIZE, ptr); \ + \ + return bin; \ +} \ + \ +term_t cbif_##l##_mac_n3(proc_t *proc, term_t *regs) \ +{ \ + term_t Key = regs[0]; \ + term_t Data = regs[1]; \ + term_t Size = regs[2]; \ + \ + if (!is_list(Key) && !is_boxed_binary(Key)) \ + badarg(Key); \ + if (!is_list(Data) && !is_boxed_binary(Data)) \ + badarg(Data); \ + if (!is_int(Size)) \ + badarg(Size); \ + \ + int trunc_size = int_value(Size); \ + if (trunc_size < 1 || trunc_size > u##_DIGEST_SIZE) \ + badarg(Size); \ + \ + int key_size = iolist_size(Key); \ + if (key_size < 0) \ + badarg(Key); \ + assert(key_size <= 65536); /* TODO: use heap_tmp_buf for a longer Key */ \ + uint8_t key_buf[key_size]; \ + iolist_flatten(Key, key_buf); \ + \ + int data_size = iolist_size(Data); \ + if (data_size < 0) \ + badarg(Data); \ + assert(data_size <= 65536); /* TODO: use heap_tmp_buf for larger Data */ \ + uint8_t data_buf[data_size]; \ + iolist_flatten(Data, data_buf); \ + \ + struct hmac_##l##_ctx ctx; \ + hmac_##l##_set_key(&ctx, key_size, key_buf); \ + hmac_##l##_update(&ctx, data_size, data_buf); \ + \ + uint8_t *ptr; \ + term_t mac = heap_make_bin(&proc->hp, trunc_size, &ptr); \ + hmac_##l##_digest(&ctx, trunc_size, ptr); \ + \ + return mac; \ } -term_t cbif_sha_update2(proc_t *proc, term_t *regs) -{ - term_t Context = regs[0]; - term_t Data = regs[1]; - - if (!is_boxed_binary(Context)) - badarg(Context); - - bits_t bs, dst; - bits_get_real(peel_boxed(Context), &bs); - if (bs.ends -bs.starts != sizeof(struct sha1_ctx) *8) - badarg(Context); - - struct sha1_ctx ctx; - bits_init_buf((uint8_t *)&ctx, sizeof(ctx), &dst); - bits_copy(&bs, &dst); - - if (!is_boxed_binary(Data) && !is_list(Data)) - badarg(Data); - - int sz = iolist_size(Data); - if (sz < 0) - badarg(Data); - assert(sz <= 65536); //TODO: use heap_tmp_buf for larger Data - uint8_t buf[sz]; - iolist_flatten(Data, buf); - - sha1_update(&ctx, sz, buf); - - uint8_t *ptr; - term_t bin = heap_make_bin(&proc->hp, sizeof(ctx), &ptr); - memcpy(ptr, &ctx, sizeof(ctx)); - - return bin; -} - -term_t cbif_sha_final1(proc_t *proc, term_t *regs) -{ - term_t Context = regs[0]; - - if (!is_boxed_binary(Context)) - badarg(Context); - - bits_t bs, dst; - bits_get_real(peel_boxed(Context), &bs); - if (bs.ends -bs.starts != sizeof(struct sha1_ctx) *8) - badarg(Context); - - struct sha1_ctx ctx; - bits_init_buf((uint8_t *)&ctx, sizeof(ctx), &dst); - bits_copy(&bs, &dst); - - uint8_t *ptr; - term_t bin = heap_make_bin(&proc->hp, SHA1_DIGEST_SIZE, &ptr); - sha1_digest(&ctx, SHA1_DIGEST_SIZE, ptr); - - return bin; -} - -term_t cbif_md5_mac_n3(proc_t *proc, term_t *regs) -{ - term_t Key = regs[0]; - term_t Data = regs[1]; - term_t Size = regs[2]; - - if (!is_list(Key) && !is_boxed_binary(Key)) - badarg(Key); - if (!is_list(Data) && !is_boxed_binary(Data)) - badarg(Data); - if (!is_int(Size)) - badarg(Size); - - int trunc_size = int_value(Size); - if (trunc_size < 1 || trunc_size > MD5_DIGEST_SIZE) - badarg(Size); - - int key_size = iolist_size(Key); - if (key_size < 0) - badarg(Key); - assert(key_size <= 65536); // TODO: use heap_tmp_buf for a longer Key - uint8_t key_buf[key_size]; - iolist_flatten(Key, key_buf); - - int data_size = iolist_size(Data); - if (data_size < 0) - badarg(Data); - assert(data_size <= 65536); // TODO: use heap_tmp_buf for larger Data - uint8_t data_buf[data_size]; - iolist_flatten(Data, data_buf); - - struct hmac_md5_ctx ctx; - hmac_md5_set_key(&ctx, key_size, key_buf); - hmac_md5_update(&ctx, data_size, data_buf); - - uint8_t *ptr; - term_t mac = heap_make_bin(&proc->hp, trunc_size, &ptr); - hmac_md5_digest(&ctx, trunc_size, ptr); - - return mac; -} - -term_t cbif_sha_mac_n3(proc_t *proc, term_t *regs) -{ - term_t Key = regs[0]; - term_t Data = regs[1]; - term_t Size = regs[2]; - - if (!is_list(Key) && !is_boxed_binary(Key)) - badarg(Key); - if (!is_list(Data) && !is_boxed_binary(Data)) - badarg(Data); - if (!is_int(Size)) - badarg(Size); - - int trunc_size = int_value(Size); - if (trunc_size < 1 || trunc_size > SHA1_DIGEST_SIZE) - badarg(Size); - - int key_size = iolist_size(Key); - if (key_size < 0) - badarg(Key); - assert(key_size <= 65536); // TODO: use heap_tmp_buf for a longer Key - uint8_t key_buf[key_size]; - iolist_flatten(Key, key_buf); - - int data_size = iolist_size(Data); - if (data_size < 0) - badarg(Data); - assert(data_size <= 65536); // TODO: use heap_tmp_buf for larger Data - uint8_t data_buf[data_size]; - iolist_flatten(Data, data_buf); - - struct hmac_sha1_ctx ctx; - hmac_sha1_set_key(&ctx, key_size, key_buf); - hmac_sha1_update(&ctx, data_size, data_buf); - - uint8_t *ptr; - term_t mac = heap_make_bin(&proc->hp, trunc_size, &ptr); - hmac_sha1_digest(&ctx, trunc_size, ptr); - - return mac; -} - -term_t cbif_sha224_mac_n3(proc_t *proc, term_t *regs) -{ - //TODO - printk("sha224_mac_n(%pt, %pt, %pt) called\n", T(regs[0]), T(regs[1]), T(regs[2])); - bif_not_implemented(); -} - -term_t cbif_sha256_mac_n3(proc_t *proc, term_t *regs) -{ - term_t Key = regs[0]; - term_t Data = regs[1]; - term_t Size = regs[2]; - - if (!is_list(Key) && !is_boxed_binary(Key)) - badarg(Key); - if (!is_list(Data) && !is_boxed_binary(Data)) - badarg(Data); - if (!is_int(Size)) - badarg(Size); - - int trunc_size = int_value(Size); - if (trunc_size < 1 || trunc_size > SHA256_DIGEST_SIZE) - badarg(Size); - - int key_size = iolist_size(Key); - if (key_size < 0) - badarg(Key); - assert(key_size <= 65536); // TODO: use heap_tmp_buf for a longer Key - uint8_t key_buf[key_size]; - iolist_flatten(Key, key_buf); - - int data_size = iolist_size(Data); - if (data_size < 0) - badarg(Data); - assert(data_size <= 65536); // TODO: use heap_tmp_buf for larger Data - uint8_t data_buf[data_size]; - iolist_flatten(Data, data_buf); - - struct hmac_sha256_ctx ctx; - hmac_sha256_set_key(&ctx, key_size, key_buf); - hmac_sha256_update(&ctx, data_size, data_buf); - - uint8_t *ptr; - term_t mac = heap_make_bin(&proc->hp, trunc_size, &ptr); - hmac_sha256_digest(&ctx, trunc_size, ptr); - - return mac; -} - -term_t cbif_sha384_mac_n3(proc_t *proc, term_t *regs) -{ - //TODO - printk("sha384_mac_n(%pt, %pt, %pt) called\n", T(regs[0]), T(regs[1]), T(regs[2])); - bif_not_implemented(); -} - -term_t cbif_sha512_mac_n3(proc_t *proc, term_t *regs) -{ - //TODO - printk("sha512_mac_n(%pt, %pt, %pt) called\n", T(regs[0]), T(regs[1]), T(regs[2])); - bif_not_implemented(); -} +DIGEST(md5, MD5) +DIGEST(sha1, SHA1) +DIGEST(sha224, SHA224) +DIGEST(sha256, SHA256) +DIGEST(sha384, SHA384) +DIGEST(sha512, SHA512) term_t cbif_aes_cbc_crypt4(proc_t *proc, term_t *regs) { diff --git a/core/bif_hash.c b/core/bif_hash.c index 4b2891c..0482e26 100644 --- a/core/bif_hash.c +++ b/core/bif_hash.c @@ -37,132 +37,6 @@ #include "bif_impl.h" -#define MD5_CONTEXT_SIZE 92 - -//TODO -// -// encode_md5_context, decode_md5_context, and update_md5_context functions is -// an overkill. Such functions allow passing context between machines. This will -// never happen. Use approach taken by sha1_* BIFs. -// - -static term_t encode_md5_context(struct md5_ctx *ctx, heap_t *hp) -{ - uint8_t *ptr; - term_t bin = heap_make_bin(hp, MD5_CONTEXT_SIZE, &ptr); - - // - // MD5 context binary layout - // + 0: state[0] - // + 4: state[1] - // + 8: state[2] - // +12: state[3] - // +16: count_low - // +20: count_high - // +24: block (64 bytes) - // +88: index - // binary size = 92 bytes - // - - PUT_UINT_32(ptr , ctx->state[0]); - PUT_UINT_32(ptr +4, ctx->state[1]); - PUT_UINT_32(ptr +8, ctx->state[2]); - PUT_UINT_32(ptr +12, ctx->state[3]); - PUT_UINT_32(ptr +16, ctx->count_low); - PUT_UINT_32(ptr +20, ctx->count_high); - memcpy(ptr + 24, ctx->block, sizeof(ctx->block)); - PUT_UINT_32(ptr +88, ctx->index); - - return bin; -} - -static int decode_md5_context(term_t Context, struct md5_ctx *ctx) -{ - if (!is_boxed(Context) || !is_binary(peel_boxed(Context))) - return -BAD_ARG; - - bits_t bs; - bits_get_real(peel_boxed(Context), &bs); - if (bs.ends - bs.starts != MD5_CONTEXT_SIZE *8) - return -BAD_ARG; - - bits_get_word(&bs, ctx->state[0]); - bits_get_word(&bs, ctx->state[1]); - bits_get_word(&bs, ctx->state[2]); - bits_get_word(&bs, ctx->state[3]); - bits_get_word(&bs, ctx->count_low); - bits_get_word(&bs, ctx->count_high); - for (int i = 0; i < sizeof(ctx->block); i++) - bits_get_octet(&bs, ctx->block[i]); - bits_get_word(&bs, ctx->index); - - return 0; -} - -static int update_md5_context(term_t IoData, struct md5_ctx *ctx) -{ - if (is_list(IoData)) - { - term_t t = IoData; - while (is_cons(t)) - { - term_t *cons = peel_cons(t); - if (is_int(cons[0])) - { - int v = int_value(cons[0]); - if (v < 0 || v > 255) - return -BAD_ARG; - uint8_t b = v; - md5_update(ctx, 1, &b); - } - else - { - int x = update_md5_context(cons[0], ctx); - if (x < 0) - return x; - } - t = cons[1]; - } - - if (t != nil) - { - int x = update_md5_context(t, ctx); - if (x < 0) - return x; - } - } - else if (is_boxed(IoData) && is_binary(peel_boxed(IoData))) - { - - bits_t bs; - bits_get_real(peel_boxed(IoData), &bs); - if (((bs.ends - bs.starts) & 7) != 0) - return -BAD_ARG; - - if ((bs.starts & 7) == 0) - { - // easy case - uint8_t *data = bs.data + bs.starts /8; - size_t len = (bs.ends - bs.starts) /8; - md5_update(ctx, len, data); - } - else - { - // tougher case - while (bits_has_octet(&bs)) - { - uint8_t o; - bits_get_octet(&bs, o); - md5_update(ctx, 1, &o); - } - } - } - else - return -BAD_ARG; - - return 0; -} - term_t cbif_hash2(proc_t *proc, term_t *regs) { term_t Term = regs[0]; @@ -223,71 +97,6 @@ term_t cbif_phash2_2(proc_t *proc, term_t *regs) return int_to_term(h, &proc->hp); } -term_t cbif_md5_1(proc_t *proc, term_t *regs) -{ - term_t Data = regs[0]; - if (!is_boxed_binary(Data) && !is_list(Data)) - badarg(Data); - - int sz = iolist_size(Data); - if (sz < 0) - badarg(Data); - // EXCEPTION POSSIBLE - uint8_t *buf = heap_tmp_buf(&proc->hp, sz); - iolist_flatten(Data, buf); - - struct md5_ctx ctx; - md5_init(&ctx); - md5_update(&ctx, sz, buf); - - uint8_t *ptr; - term_t bin = heap_make_bin(&proc->hp, MD5_DIGEST_SIZE, &ptr); - md5_digest(&ctx, MD5_DIGEST_SIZE, ptr); - - return bin; -} - -term_t cbif_md5_init0(proc_t *proc, term_t *regs) -{ - struct md5_ctx ctx; - md5_init(&ctx); - - return encode_md5_context(&ctx, &proc->hp); -} - -term_t cbif_md5_update2(proc_t *proc, term_t *regs) -{ - term_t Context = regs[0]; - term_t IoData = regs[1]; - - struct md5_ctx ctx; - if (decode_md5_context(Context, &ctx) < 0) - badarg(Context); - - int x = update_md5_context(IoData, &ctx); - if (x == -TOO_DEEP) - fail(A_SYSTEM_LIMIT); - else if (x < 0) - badarg(IoData); - - return encode_md5_context(&ctx, &proc->hp); -} - -term_t cbif_md5_final1(proc_t *proc, term_t *regs) -{ - term_t Context = regs[0]; - - struct md5_ctx ctx; - if (decode_md5_context(Context, &ctx) < 0) - badarg(Context); - - uint8_t *ptr; - term_t bin = heap_make_bin(&proc->hp, MD5_DIGEST_SIZE, &ptr); - md5_digest(&ctx, MD5_DIGEST_SIZE, ptr); - - return bin; -} - term_t cbif_crc32_2(proc_t *proc, term_t *regs) { term_t OldCrc32 = regs[0];