summaryrefslogtreecommitdiff
path: root/src/trust.c
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2020-10-09 13:40:14 +0300
committerTimo Teräs <timo.teras@iki.fi>2020-10-09 16:09:19 +0300
commit705e002bb0ab1a317df73e4efac08ebd25dd4d8c (patch)
tree37b262e1627188df64ea69e74b44df203b85b786 /src/trust.c
parenta627ab8eb8387ebf5735cf525ae72bfa159aa39a (diff)
downloadapk-tools-705e002bb0ab1a317df73e4efac08ebd25dd4d8c.tar.gz
apk-tools-705e002bb0ab1a317df73e4efac08ebd25dd4d8c.tar.bz2
apk-tools-705e002bb0ab1a317df73e4efac08ebd25dd4d8c.tar.xz
apk-tools-705e002bb0ab1a317df73e4efac08ebd25dd4d8c.zip
rename adb_trust to apk_trust, and use it as package signature keystore too
Diffstat (limited to 'src/trust.c')
-rw-r--r--src/trust.c165
1 files changed, 165 insertions, 0 deletions
diff --git a/src/trust.c b/src/trust.c
new file mode 100644
index 0000000..6f63137
--- /dev/null
+++ b/src/trust.c
@@ -0,0 +1,165 @@
+#include <errno.h>
+#include <stdio.h>
+#include <openssl/bio.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+
+#include "apk_defines.h"
+#include "apk_trust.h"
+#include "apk_io.h"
+
+/* Trust */
+int apk_pkey_init(struct apk_pkey *pkey, EVP_PKEY *key)
+{
+ unsigned char dig[EVP_MAX_MD_SIZE], *pub = NULL;
+ unsigned int dlen = sizeof dig;
+ int len;
+
+ if ((len = i2d_PublicKey(key, &pub)) < 0) return -EIO;
+ EVP_Digest(pub, len, dig, &dlen, EVP_sha512(), NULL);
+ memcpy(pkey->id, dig, sizeof pkey->id);
+ OPENSSL_free(pub);
+
+ pkey->key = key;
+ return 0;
+}
+
+void apk_pkey_free(struct apk_pkey *pkey)
+{
+ EVP_PKEY_free(pkey->key);
+}
+
+int apk_pkey_load(struct apk_pkey *pkey, int dirfd, const char *fn)
+{
+ EVP_PKEY *key;
+ BIO *bio;
+ int fd;
+
+ fd = openat(dirfd, fn, O_RDONLY|O_CLOEXEC);
+ if (fd < 0) return -errno;
+
+ bio = BIO_new_fp(fdopen(fd, "r"), BIO_CLOSE);
+ if (!bio) return -ENOMEM;
+
+ key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
+ if (!key) {
+ BIO_reset(bio);
+ key = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
+ }
+ ERR_clear_error();
+
+ BIO_free(bio);
+ if (!key) return -EBADMSG;
+
+ apk_pkey_init(pkey, key);
+ return 0;
+}
+
+static struct apk_trust_key *apk_trust_load_key(int dirfd, const char *filename)
+{
+ struct apk_trust_key *key;
+ int r;
+
+ key = calloc(1, sizeof *key);
+ if (!key) return ERR_PTR(-ENOMEM);
+
+ r = apk_pkey_load(&key->key, dirfd, filename);
+ if (r) {
+ free(key);
+ return ERR_PTR(-ENOKEY);
+ }
+
+ list_init(&key->key_node);
+ key->filename = strdup(filename);
+ return key;
+}
+
+static int __apk_trust_load_pubkey(void *pctx, int dirfd, const char *filename)
+{
+ struct apk_trust *trust = pctx;
+ struct apk_trust_key *key = apk_trust_load_key(dirfd, filename);
+
+ if (!IS_ERR(key))
+ list_add_tail(&key->key_node, &trust->trusted_key_list);
+
+ return 0;
+}
+
+int apk_trust_init(struct apk_trust *trust, int dirfd, struct apk_string_array *pkey_files)
+{
+ char **fn;
+
+ *trust = (struct apk_trust){
+ .mdctx = EVP_MD_CTX_new(),
+ };
+ if (!trust->mdctx) return -ENOMEM;
+ EVP_MD_CTX_set_flags(trust->mdctx, EVP_MD_CTX_FLAG_FINALISE);
+ list_init(&trust->trusted_key_list);
+ list_init(&trust->private_key_list);
+ apk_dir_foreach_file(dirfd, __apk_trust_load_pubkey, trust);
+
+ foreach_array_item(fn, pkey_files) {
+ struct apk_trust_key *key = apk_trust_load_key(AT_FDCWD, *fn);
+ if (IS_ERR(key)) return PTR_ERR(key);
+ list_add_tail(&key->key_node, &trust->private_key_list);
+ }
+
+ return 0;
+}
+
+static void __apk_trust_free_keys(struct list_head *h)
+{
+ struct apk_trust_key *tkey, *n;
+
+ list_for_each_entry_safe(tkey, n, h, key_node) {
+ list_del(&tkey->key_node);
+ apk_pkey_free(&tkey->key);
+ free(tkey->filename);
+ free(tkey);
+ }
+}
+
+void apk_trust_free(struct apk_trust *trust)
+{
+ if (!trust->mdctx) return;
+ __apk_trust_free_keys(&trust->trusted_key_list);
+ __apk_trust_free_keys(&trust->private_key_list);
+ EVP_MD_CTX_free(trust->mdctx);
+}
+
+struct apk_pkey *apk_trust_key_by_name(struct apk_trust *trust, const char *filename)
+{
+ struct apk_trust_key *tkey;
+
+ list_for_each_entry(tkey, &trust->trusted_key_list, key_node)
+ if (tkey->filename && strcmp(tkey->filename, filename) == 0)
+ return &tkey->key;
+ return NULL;
+}
+
+
+/* Command group for signing */
+
+#include "apk_applet.h"
+
+#define SIGNING_OPTIONS(OPT) \
+ OPT(OPT_SIGN_sign_key, APK_OPT_ARG "sign-key")
+
+APK_OPT_GROUP(options_signing, "Signing", SIGNING_OPTIONS);
+
+static int option_parse_signing(void *ctx, struct apk_ctx *ac, int optch, const char *optarg)
+{
+ switch (optch) {
+ case OPT_SIGN_sign_key:
+ *apk_string_array_add(&ac->private_keys) = (char*) optarg;
+ break;
+ default:
+ return -ENOTSUP;
+ }
+ return 0;
+}
+
+const struct apk_option_group optgroup_signing = {
+ .desc = options_signing,
+ .parse = option_parse_signing,
+};