2021-06-09 15:21:40 +00:00
|
|
|
/* apk_crypt.c - Alpine Package Keeper (APK)
|
|
|
|
*
|
|
|
|
* Copyright (C) 2021 Timo Teräs <timo.teras@iki.fi>
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-only
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef APK_CRYPTO_H
|
|
|
|
#define APK_CRYPTO_H
|
|
|
|
|
|
|
|
#include <assert.h>
|
2021-06-11 10:51:13 +00:00
|
|
|
#include <string.h>
|
2021-06-09 15:21:40 +00:00
|
|
|
#include <openssl/evp.h>
|
2021-06-19 13:09:30 +00:00
|
|
|
#include "apk_defines.h"
|
2021-06-09 15:21:40 +00:00
|
|
|
#include "apk_openssl.h"
|
|
|
|
|
|
|
|
// Digest
|
|
|
|
|
|
|
|
struct apk_digest_ctx {
|
|
|
|
EVP_MD_CTX *mdctx;
|
|
|
|
uint8_t alg;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define APK_DIGEST_NONE 0x00
|
|
|
|
#define APK_DIGEST_MD5 0x01
|
|
|
|
#define APK_DIGEST_SHA1 0x02
|
|
|
|
#define APK_DIGEST_SHA256 0x03
|
|
|
|
#define APK_DIGEST_SHA512 0x04
|
2021-10-25 14:14:00 +00:00
|
|
|
#define APK_DIGEST_SHA256_160 0x05
|
2021-06-09 15:21:40 +00:00
|
|
|
|
|
|
|
#define APK_DIGEST_MAX_LENGTH 64 // longest is SHA512
|
|
|
|
|
|
|
|
const char *apk_digest_alg_str(uint8_t);
|
|
|
|
uint8_t apk_digest_alg_from_csum(int);
|
|
|
|
|
|
|
|
struct apk_digest {
|
|
|
|
uint8_t alg, len;
|
|
|
|
uint8_t data[APK_DIGEST_MAX_LENGTH];
|
|
|
|
};
|
|
|
|
|
|
|
|
#define APK_DIGEST_BLOB(d) APK_BLOB_PTR_LEN((void*)((d).data), (d).len)
|
|
|
|
|
|
|
|
static inline const EVP_MD *apk_digest_alg_to_evp(uint8_t alg) {
|
|
|
|
switch (alg) {
|
|
|
|
case APK_DIGEST_NONE: return EVP_md_null();
|
|
|
|
case APK_DIGEST_MD5: return EVP_md5();
|
|
|
|
case APK_DIGEST_SHA1: return EVP_sha1();
|
2021-10-25 14:14:00 +00:00
|
|
|
case APK_DIGEST_SHA256_160:
|
2021-06-09 15:21:40 +00:00
|
|
|
case APK_DIGEST_SHA256: return EVP_sha256();
|
|
|
|
case APK_DIGEST_SHA512: return EVP_sha512();
|
|
|
|
default:
|
|
|
|
assert(alg);
|
|
|
|
return EVP_md_null();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-09 20:12:52 +00:00
|
|
|
int apk_digest_alg_len(uint8_t alg);
|
|
|
|
uint8_t apk_digest_alg_by_len(int len);
|
|
|
|
|
|
|
|
static inline int apk_digest_cmp(struct apk_digest *a, struct apk_digest *b) {
|
|
|
|
if (a->alg != b->alg) return b->alg - a->alg;
|
|
|
|
return memcmp(a->data, b->data, a->len);
|
2021-06-09 15:21:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void apk_digest_reset(struct apk_digest *d) {
|
|
|
|
d->alg = APK_DIGEST_NONE;
|
2021-06-09 20:12:52 +00:00
|
|
|
d->len = 0;
|
2021-06-09 15:21:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void apk_digest_set(struct apk_digest *d, uint8_t alg) {
|
|
|
|
d->alg = alg;
|
|
|
|
d->len = apk_digest_alg_len(alg);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int apk_digest_calc(struct apk_digest *d, uint8_t alg, const void *ptr, size_t sz)
|
|
|
|
{
|
|
|
|
unsigned int md_sz = sizeof d->data;
|
|
|
|
if (EVP_Digest(ptr, sz, d->data, &md_sz, apk_digest_alg_to_evp(alg), 0) != 1)
|
2021-06-19 13:09:30 +00:00
|
|
|
return -APKE_CRYPTO_ERROR;
|
2021-06-09 15:21:40 +00:00
|
|
|
d->alg = alg;
|
2021-10-25 14:14:00 +00:00
|
|
|
d->len = apk_digest_alg_len(alg);
|
2021-06-09 15:21:40 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int apk_digest_ctx_init(struct apk_digest_ctx *dctx, uint8_t alg) {
|
2021-07-30 13:38:53 +00:00
|
|
|
dctx->alg = alg;
|
2021-06-09 15:21:40 +00:00
|
|
|
dctx->mdctx = EVP_MD_CTX_new();
|
|
|
|
if (!dctx->mdctx) return -ENOMEM;
|
2021-06-12 05:40:53 +00:00
|
|
|
#ifdef EVP_MD_CTX_FLAG_FINALISE
|
2021-06-09 15:21:40 +00:00
|
|
|
EVP_MD_CTX_set_flags(dctx->mdctx, EVP_MD_CTX_FLAG_FINALISE);
|
2021-06-12 05:40:53 +00:00
|
|
|
#endif
|
2021-06-09 15:21:40 +00:00
|
|
|
EVP_DigestInit_ex(dctx->mdctx, apk_digest_alg_to_evp(alg), 0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void apk_digest_ctx_free(struct apk_digest_ctx *dctx) {
|
|
|
|
EVP_MD_CTX_free(dctx->mdctx);
|
|
|
|
dctx->mdctx = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int apk_digest_ctx_update(struct apk_digest_ctx *dctx, const void *ptr, size_t sz) {
|
2021-06-19 13:09:30 +00:00
|
|
|
return EVP_DigestUpdate(dctx->mdctx, ptr, sz) == 1 ? 0 : -APKE_CRYPTO_ERROR;
|
2021-06-09 15:21:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline int apk_digest_ctx_final(struct apk_digest_ctx *dctx, struct apk_digest *d) {
|
|
|
|
unsigned int mdlen = sizeof d->data;
|
|
|
|
if (EVP_DigestFinal_ex(dctx->mdctx, d->data, &mdlen) != 1) {
|
|
|
|
apk_digest_reset(d);
|
2021-06-19 13:09:30 +00:00
|
|
|
return -APKE_CRYPTO_ERROR;
|
2021-06-09 15:21:40 +00:00
|
|
|
}
|
|
|
|
d->alg = dctx->alg;
|
2021-10-25 14:14:00 +00:00
|
|
|
d->len = apk_digest_alg_len(d->alg);
|
2021-06-09 15:21:40 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "apk_blob.h"
|
2021-06-09 20:12:52 +00:00
|
|
|
uint8_t apk_digest_from_blob(struct apk_digest *d, apk_blob_t b);
|
2021-06-09 15:21:40 +00:00
|
|
|
static inline int apk_digest_cmp_csum(const struct apk_digest *d, const struct apk_checksum *csum)
|
|
|
|
{
|
|
|
|
return apk_blob_compare(APK_DIGEST_BLOB(*d), APK_BLOB_CSUM(*csum));
|
|
|
|
}
|
|
|
|
static inline void apk_checksum_from_digest(struct apk_checksum *csum, const struct apk_digest *d)
|
|
|
|
{
|
2021-09-03 13:29:55 +00:00
|
|
|
if (d->len > sizeof csum->data) {
|
|
|
|
csum->type = APK_CHECKSUM_NONE;
|
|
|
|
} else {
|
|
|
|
csum->type = d->len;
|
|
|
|
memcpy(csum->data, d->data, d->len);
|
|
|
|
}
|
2021-06-09 15:21:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Asymmetric keys
|
|
|
|
|
|
|
|
struct apk_pkey {
|
|
|
|
uint8_t id[16];
|
|
|
|
EVP_PKEY *key;
|
|
|
|
};
|
|
|
|
|
|
|
|
int apk_pkey_init(struct apk_pkey *pkey, EVP_PKEY *key);
|
|
|
|
void apk_pkey_free(struct apk_pkey *pkey);
|
|
|
|
int apk_pkey_load(struct apk_pkey *pkey, int dirfd, const char *fn);
|
|
|
|
|
|
|
|
// Signing
|
|
|
|
|
|
|
|
int apk_sign_start(struct apk_digest_ctx *, struct apk_pkey *);
|
|
|
|
int apk_sign(struct apk_digest_ctx *, void *, size_t *);
|
|
|
|
int apk_verify_start(struct apk_digest_ctx *, struct apk_pkey *);
|
|
|
|
int apk_verify(struct apk_digest_ctx *, void *, size_t);
|
|
|
|
|
|
|
|
// Initializiation
|
|
|
|
|
|
|
|
#if OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
|
|
|
|
|
|
|
|
static inline void apk_crypto_cleanup(void)
|
|
|
|
{
|
|
|
|
EVP_cleanup();
|
|
|
|
#ifndef OPENSSL_NO_ENGINE
|
|
|
|
ENGINE_cleanup();
|
|
|
|
#endif
|
|
|
|
CRYPTO_cleanup_all_ex_data();
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void apk_crypto_init(void)
|
|
|
|
{
|
|
|
|
atexit(apk_crypto_cleanup);
|
|
|
|
OpenSSL_add_all_algorithms();
|
|
|
|
#ifndef OPENSSL_NO_ENGINE
|
|
|
|
ENGINE_load_builtin_engines();
|
|
|
|
ENGINE_register_all_complete();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
static inline void apk_crypto_init(void) {}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif
|