#include #include #include "apk_crypto.h" // Union tag is in apk_digest_ctx->alg union digest_state { crypto_hash_sha256_state sha256; crypto_hash_sha512_state sha512; br_sha1_context sha1; br_md5_context md5; }; static const char *apk_digest_str[] = { [APK_DIGEST_NONE] = "none", [APK_DIGEST_MD5] = "md5", [APK_DIGEST_SHA1] = "sha1", [APK_DIGEST_SHA256_160] = "sha256-160", [APK_DIGEST_SHA256] = "sha256", [APK_DIGEST_SHA512] = "sha512", }; const char *apk_digest_alg_str(uint8_t alg) { const char *alg_str = "unknown"; if (alg < ARRAY_SIZE(apk_digest_str)) alg_str = apk_digest_str[alg]; return alg_str; } int apk_digest_alg_len(uint8_t alg) { switch (alg) { case APK_DIGEST_MD5: return 16; case APK_DIGEST_SHA1: return 20; case APK_DIGEST_SHA256_160: return 20; case APK_DIGEST_SHA256: return 32; case APK_DIGEST_SHA512: return 64; default: return 0; } } uint8_t apk_digest_alg_by_len(int len) { switch (len) { case 0: return APK_DIGEST_NONE; case 16: return APK_DIGEST_MD5; case 20: return APK_DIGEST_SHA1; case 32: return APK_DIGEST_SHA256; case 64: return APK_DIGEST_SHA512; default: return APK_DIGEST_NONE; } } uint8_t apk_digest_alg_from_csum(int csum) { switch (csum) { case APK_CHECKSUM_NONE: return APK_DIGEST_NONE; case APK_CHECKSUM_MD5: return APK_DIGEST_MD5; case APK_CHECKSUM_SHA1: return APK_DIGEST_SHA1; default: return APK_DIGEST_NONE; } } uint8_t apk_digest_from_blob(struct apk_digest *d, apk_blob_t b) { d->alg = apk_digest_alg_by_len(b.len); d->len = 0; if (d->alg != APK_DIGEST_NONE) { d->len = b.len; memcpy(d->data, b.ptr, d->len); } return d->alg; } int apk_digest_calc(struct apk_digest *d, uint8_t alg, const void *ptr, size_t sz) { union digest_state state; switch (alg) { case APK_DIGEST_SHA256: case APK_DIGEST_SHA256_160: crypto_hash_sha256(d->data, ptr, sz); break; case APK_DIGEST_SHA512: crypto_hash_sha512(d->data, ptr, sz); break; case APK_DIGEST_NONE: break; case APK_DIGEST_MD5: br_md5_init(&state.md5); br_md5_update(&state.md5, ptr, sz); br_md5_out(&state.md5, d->data); break; case APK_DIGEST_SHA1: br_sha1_init(&state.sha1); br_sha1_update(&state.sha1, ptr, sz); br_sha1_out(&state.sha1, d->data); break; default: return -APKE_CRYPTO_NOT_SUPPORTED; } d->alg = alg; d->len = apk_digest_alg_len(d->alg); return 0; } int apk_digest_ctx_init(struct apk_digest_ctx *dctx, uint8_t alg) { union digest_state *state; dctx->impl = malloc(sizeof(union digest_state)); if (dctx->impl == NULL) { return -ENOMEM; } state = (union digest_state *) dctx->impl; dctx->alg = alg; switch (alg) { case APK_DIGEST_SHA256: case APK_DIGEST_SHA256_160: crypto_hash_sha256_init(&state->sha256); break; case APK_DIGEST_SHA512: crypto_hash_sha512_init(&state->sha512); break; case APK_DIGEST_MD5: br_md5_init(&state->md5); break; case APK_DIGEST_SHA1: br_sha1_init(&state->sha1); break; case APK_DIGEST_NONE: break; default: free(dctx->impl); return -APKE_CRYPTO_NOT_SUPPORTED; } return 0; } int apk_digest_ctx_reset(struct apk_digest_ctx *dctx, uint8_t alg) { apk_digest_ctx_free(dctx); return apk_digest_ctx_init(dctx, alg); } void apk_digest_ctx_free(struct apk_digest_ctx *dctx) { if (dctx->impl == NULL) { return; } switch (dctx->alg) { case APK_DIGEST_NONE: case APK_DIGEST_MD5: case APK_DIGEST_SHA1: case APK_DIGEST_SHA256: case APK_DIGEST_SHA512: case APK_DIGEST_SHA256_160: free(dctx->impl); dctx->impl = NULL; break; default: /* illegal state, don't touch impl? */ return; } } int apk_digest_ctx_update(struct apk_digest_ctx *dctx, const void *ptr, size_t sz) { union digest_state *state = (union digest_state *) dctx->impl; switch (dctx->alg) { case APK_DIGEST_SHA256: case APK_DIGEST_SHA256_160: crypto_hash_sha256_update(&state->sha256, ptr, sz); break; case APK_DIGEST_SHA512: crypto_hash_sha512_update(&state->sha512, ptr, sz); break; case APK_DIGEST_MD5: br_md5_update(&state->md5, ptr, sz); break; case APK_DIGEST_SHA1: br_sha1_update(&state->sha1, ptr, sz); break; case APK_DIGEST_NONE: break; default: return -APKE_CRYPTO_NOT_SUPPORTED; } return 0; } int apk_digest_ctx_final(struct apk_digest_ctx *dctx, struct apk_digest *d) { union digest_state *state = (union digest_state *) dctx->impl; switch (dctx->alg) { case APK_DIGEST_SHA256: case APK_DIGEST_SHA256_160: crypto_hash_sha256_final(&state->sha256, d->data); break; case APK_DIGEST_SHA512: crypto_hash_sha512_final(&state->sha512, d->data); break; case APK_DIGEST_MD5: br_md5_out(&state->md5, d->data); break; case APK_DIGEST_SHA1: br_sha1_out(&state->sha1, d->data); break; case APK_DIGEST_NONE: break; default: return -APKE_CRYPTO_NOT_SUPPORTED; } d->alg = dctx->alg; d->len = apk_digest_alg_len(d->alg); return 0; }