apk-tools/src/crypto_digest.c

210 lines
4.3 KiB
C

#include <sodium.h>
#include "apk_crypto.h"
/*
static inline int apk_digest_ctx_init(struct apk_digest_ctx *dctx, uint8_t alg) {
dctx->alg = alg;
dctx->mdctx = EVP_MD_CTX_new();
if (!dctx->mdctx) return -ENOMEM;
#ifdef EVP_MD_CTX_FLAG_FINALISE
EVP_MD_CTX_set_flags(dctx->mdctx, EVP_MD_CTX_FLAG_FINALISE);
#endif
if (alg != APK_DIGEST_NONE) EVP_DigestInit_ex(dctx->mdctx, apk_digest_alg_to_evp(alg), 0);
return 0;
}
*/
union digest_state {
crypto_hash_sha256_state sha256;
crypto_hash_sha512_state sha512;
EVP_MD_CTX *mdctx;
};
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_calc(struct apk_digest *d, uint8_t alg, const void *ptr, size_t sz)
{
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:
break;
case APK_DIGEST_SHA1:
break;
default:
return -APKE_CRYPTO_NOT_SUPPORTED;
}
d->alg = alg;
return 0;
}
int apk_digest_ctx_init(struct apk_digest_ctx *dctx, uint8_t alg)
{
union digest_state *state = NULL;
const EVP_MD *evp_md = NULL;
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_NONE:
evp_md = EVP_md_null();
case APK_DIGEST_MD5:
evp_md = EVP_md5();
break;
case APK_DIGEST_SHA1:
evp_md = EVP_sha1();
break;
default:
free(dctx->impl);
return -APKE_CRYPTO_NOT_SUPPORTED;
}
if (evp_md != NULL) {
state->mdctx = EVP_MD_CTX_new();
if (state->mdctx == NULL) {
goto a;
}
#ifdef EVP_MD_CTX_FLAG_FINALISE
EVP_MD_CTX_set_flags(dctx->mdctx, EVP_MD_CTX_FLAG_FINALISE);
#endif
EVP_DigestInit_ex(dctx->mdctx, apk_digest_alg_to_evp(alg), 0);
}
return 0;
a:
free(dctx->impl);
return -APKE_CRYPTO_ERROR;
}
void apk_digest_ctx_reset(struct apk_digest_ctx *dctx, uint8_t alg)
{
apk_digest_ctx_free(dctx);
apk_digest_ctx_init(dctx, alg);
}
void apk_digest_ctx_free(struct apk_digest_ctx *dctx)
{
union digest_state *state = (union digest_state *) dctx->impl;
if (dctx->impl == NULL) {
return;
}
switch (dctx->alg) {
case APK_DIGEST_NONE:
case APK_DIGEST_MD5:
case APK_DIGEST_SHA1:
EVP_MD_CTX_free(state->mdctx);
case APK_DIGEST_SHA256:
case APK_DIGEST_SHA512:
case APK_DIGEST_SHA256_160:
break;
default:
/* illegal state, don't touch impl? */
return;
}
free(dctx->impl);
dctx->impl = NULL;
}
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_NONE:
case APK_DIGEST_MD5:
case APK_DIGEST_SHA1:
if (EVP_DigestUpdate(state->mdctx, ptr, sz) != 1) {
return -APKE_CRYPTO_ERROR;
}
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 = dctx->impl;
unsigned int mdlen;
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_NONE:
case APK_DIGEST_MD5:
case APK_DIGEST_SHA1:
mdlen = sizeof d->data;
if (EVP_DigestFinal_ex(state->mdctx, d->data, &mdlen) != 1) {
apk_digest_reset(d);
return -APKE_CRYPTO_ERROR;
}
break;
default:
return -APKE_CRYPTO_NOT_SUPPORTED;
}
d->alg = dctx->alg;
d->len = apk_digest_alg_len(d->alg);
return 0;
}