210 lines
4.3 KiB
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;
|
|
}
|