summaryrefslogtreecommitdiff
path: root/src/apk_crypto.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/apk_crypto.h')
-rw-r--r--src/apk_crypto.h174
1 files changed, 174 insertions, 0 deletions
diff --git a/src/apk_crypto.h b/src/apk_crypto.h
new file mode 100644
index 0000000..35d27aa
--- /dev/null
+++ b/src/apk_crypto.h
@@ -0,0 +1,174 @@
+/* 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>
+#include <errno.h>
+#include <openssl/evp.h>
+#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
+
+#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();
+ case APK_DIGEST_SHA256: return EVP_sha256();
+ case APK_DIGEST_SHA512: return EVP_sha512();
+ default:
+ assert(alg);
+ return EVP_md_null();
+ }
+}
+
+static inline 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: return 32;
+ case APK_DIGEST_SHA512: return 64;
+ default:
+ assert(alg);
+ return 0;
+ }
+}
+
+static inline void apk_digest_reset(struct apk_digest *d) {
+ d->len = 0;
+ d->alg = APK_DIGEST_NONE;
+}
+
+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)
+ return -EIO;
+ d->alg = alg;
+ d->len = md_sz;
+ return 0;
+}
+
+static inline int apk_digest_ctx_init(struct apk_digest_ctx *dctx, uint8_t alg) {
+ dctx->mdctx = EVP_MD_CTX_new();
+ if (!dctx->mdctx) return -ENOMEM;
+ dctx->alg = alg;
+ EVP_MD_CTX_set_flags(dctx->mdctx, EVP_MD_CTX_FLAG_FINALISE);
+ 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) {
+ return EVP_DigestUpdate(dctx->mdctx, ptr, sz) == 1 ? 0 : -EIO;
+}
+
+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);
+ return -EIO;
+ }
+ d->alg = dctx->alg;
+ d->len = mdlen;
+ return 0;
+}
+
+#include "apk_blob.h"
+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)
+{
+ csum->type = d->len;
+ memcpy(csum->data, d->data, d->len);
+}
+
+// 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