rename adb_trust to apk_trust, and use it as package signature keystore too
parent
a627ab8eb8
commit
705e002bb0
|
@ -19,9 +19,8 @@ ZLIB_LIBS := $(shell $(PKG_CONFIG) --libs zlib)
|
|||
libapk_soname := 3.12.0
|
||||
libapk_so := $(obj)/libapk.so.$(libapk_soname)
|
||||
libapk.so.$(libapk_soname)-objs := \
|
||||
adb.o adb_trust.o \
|
||||
common.o context.o database.o package.o commit.o solver.o \
|
||||
version.o atom.o blob.o hash.o print.o \
|
||||
adb.o common.o context.o database.o package.o commit.o solver.o \
|
||||
trust.o version.o atom.o blob.o hash.o print.o \
|
||||
io.o io_url.o io_gunzip.o io_archive.o
|
||||
|
||||
libapk.so.$(libapk_soname)-libs := libfetch/libfetch.a
|
||||
|
|
122
src/adb.c
122
src/adb.c
|
@ -6,9 +6,12 @@
|
|||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "adb.h"
|
||||
#include "apk_blob.h"
|
||||
#include "apk_trust.h"
|
||||
|
||||
/* Block enumeration */
|
||||
static inline struct adb_block *adb_block_validate(struct adb_block *blk, apk_blob_t b)
|
||||
|
@ -60,7 +63,7 @@ void adb_reset(struct adb *db)
|
|||
db->adb.len = 0;
|
||||
}
|
||||
|
||||
static int __adb_m_parse(struct adb *db, struct adb_trust *t)
|
||||
static int __adb_m_parse(struct adb *db, struct apk_trust *t)
|
||||
{
|
||||
struct adb_verify_ctx vfy = {};
|
||||
struct adb_block *blk;
|
||||
|
@ -95,13 +98,13 @@ static int __adb_m_parse(struct adb *db, struct adb_trust *t)
|
|||
return r;
|
||||
}
|
||||
|
||||
int adb_m_blob(struct adb *db, apk_blob_t blob, struct adb_trust *t)
|
||||
int adb_m_blob(struct adb *db, apk_blob_t blob, struct apk_trust *t)
|
||||
{
|
||||
*db = (struct adb) { .data = blob };
|
||||
return __adb_m_parse(db, t);
|
||||
}
|
||||
|
||||
int adb_m_map(struct adb *db, int fd, uint32_t expected_schema, struct adb_trust *t)
|
||||
int adb_m_map(struct adb *db, int fd, uint32_t expected_schema, struct apk_trust *t)
|
||||
{
|
||||
struct stat st;
|
||||
struct adb_header *hdr;
|
||||
|
@ -810,7 +813,7 @@ int adb_c_block_copy(struct apk_ostream *os, struct adb_block *b, struct apk_ist
|
|||
return r;
|
||||
}
|
||||
|
||||
int adb_c_create(struct apk_ostream *os, struct adb *db, struct adb_trust *t)
|
||||
int adb_c_create(struct apk_ostream *os, struct adb *db, struct apk_trust *t)
|
||||
{
|
||||
if (IS_ERR(os)) return PTR_ERR(os);
|
||||
if (db->hdr.magic != htole32(ADB_FORMAT_MAGIC)) {
|
||||
|
@ -824,6 +827,117 @@ ret:
|
|||
return apk_ostream_close(os);
|
||||
}
|
||||
|
||||
/* Signatures */
|
||||
static int adb_verify_ctx_calc(struct adb_verify_ctx *vfy, unsigned int hash_alg, apk_blob_t data, apk_blob_t *pmd)
|
||||
{
|
||||
const EVP_MD *evp;
|
||||
apk_blob_t md;
|
||||
|
||||
switch (hash_alg) {
|
||||
case ADB_HASH_SHA512:
|
||||
evp = EVP_sha512();
|
||||
*pmd = md = APK_BLOB_BUF(vfy->sha512);
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (!(vfy->calc & (1 << hash_alg))) {
|
||||
unsigned int sz = md.len;
|
||||
if (APK_BLOB_IS_NULL(data)) return -ENOMSG;
|
||||
if (EVP_Digest(data.ptr, data.len, (unsigned char*) md.ptr, &sz, evp, NULL) != 1 ||
|
||||
sz != md.len)
|
||||
return -EIO;
|
||||
vfy->calc |= (1 << hash_alg);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int adb_trust_write_signatures(struct apk_trust *trust, struct adb *db, struct adb_verify_ctx *vfy, struct apk_ostream *os)
|
||||
{
|
||||
union {
|
||||
struct adb_sign_hdr hdr;
|
||||
struct adb_sign_v0 v0;
|
||||
unsigned char buf[8192];
|
||||
} sig;
|
||||
struct apk_trust_key *tkey;
|
||||
apk_blob_t md;
|
||||
size_t siglen;
|
||||
int r;
|
||||
|
||||
if (!vfy) {
|
||||
vfy = alloca(sizeof *vfy);
|
||||
memset(vfy, 0, sizeof *vfy);
|
||||
}
|
||||
|
||||
r = adb_verify_ctx_calc(vfy, ADB_HASH_SHA512, db->adb, &md);
|
||||
if (r) return r;
|
||||
|
||||
list_for_each_entry(tkey, &trust->private_key_list, key_node) {
|
||||
sig.v0 = (struct adb_sign_v0) {
|
||||
.hdr.sign_ver = 0,
|
||||
.hdr.hash_alg = ADB_HASH_SHA512,
|
||||
};
|
||||
memcpy(sig.v0.id, tkey->key.id, sizeof(sig.v0.id));
|
||||
|
||||
siglen = sizeof sig.buf - sizeof sig.v0;
|
||||
EVP_MD_CTX_set_pkey_ctx(trust->mdctx, NULL);
|
||||
if (EVP_DigestSignInit(trust->mdctx, NULL, EVP_sha512(), NULL, tkey->key.key) != 1 ||
|
||||
EVP_DigestUpdate(trust->mdctx, &db->hdr, sizeof db->hdr) != 1 ||
|
||||
EVP_DigestUpdate(trust->mdctx, &sig.hdr.sign_ver, sizeof sig.hdr.sign_ver) != 1 ||
|
||||
EVP_DigestUpdate(trust->mdctx, &sig.hdr.hash_alg, sizeof sig.hdr.hash_alg) != 1 ||
|
||||
EVP_DigestUpdate(trust->mdctx, md.ptr, md.len) != 1 ||
|
||||
EVP_DigestSignFinal(trust->mdctx, sig.v0.sig, &siglen) != 1) {
|
||||
ERR_print_errors_fp(stdout);
|
||||
goto err_io;
|
||||
}
|
||||
|
||||
r = adb_c_block(os, ADB_BLOCK_SIG, APK_BLOB_PTR_LEN((char*) &sig, sizeof(sig.v0) + siglen));
|
||||
if (r < 0) goto err;
|
||||
}
|
||||
return 0;
|
||||
err_io:
|
||||
r = -EIO;
|
||||
err:
|
||||
apk_ostream_cancel(os, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
int adb_trust_verify_signature(struct apk_trust *trust, struct adb *db, struct adb_verify_ctx *vfy, apk_blob_t sigb)
|
||||
{
|
||||
struct apk_trust_key *tkey;
|
||||
struct adb_sign_hdr *sig;
|
||||
struct adb_sign_v0 *sig0;
|
||||
apk_blob_t md;
|
||||
|
||||
if (APK_BLOB_IS_NULL(db->adb)) return -ENOMSG;
|
||||
if (sigb.len < sizeof(struct adb_sign_hdr)) return -EBADMSG;
|
||||
|
||||
sig = (struct adb_sign_hdr *) sigb.ptr;
|
||||
sig0 = (struct adb_sign_v0 *) sigb.ptr;
|
||||
if (sig->sign_ver != 0) return -ENOSYS;
|
||||
|
||||
list_for_each_entry(tkey, &trust->trusted_key_list, key_node) {
|
||||
if (memcmp(sig0->id, tkey->key.id, sizeof sig0->id) != 0) continue;
|
||||
if (adb_verify_ctx_calc(vfy, sig->hash_alg, db->adb, &md) != 0) continue;
|
||||
|
||||
EVP_MD_CTX_set_pkey_ctx(trust->mdctx, NULL);
|
||||
if (EVP_DigestVerifyInit(trust->mdctx, NULL, EVP_sha512(), NULL, tkey->key.key) != 1 ||
|
||||
EVP_DigestUpdate(trust->mdctx, &db->hdr, sizeof db->hdr) != 1 ||
|
||||
EVP_DigestUpdate(trust->mdctx, &sig->sign_ver, sizeof sig->sign_ver) != 1 ||
|
||||
EVP_DigestUpdate(trust->mdctx, &sig->hash_alg, sizeof sig->hash_alg) != 1 ||
|
||||
EVP_DigestUpdate(trust->mdctx, md.ptr, md.len) != 1 ||
|
||||
EVP_DigestVerifyFinal(trust->mdctx, sig0->sig, sigb.len - sizeof(*sig0)) != 1) {
|
||||
ERR_clear_error();
|
||||
continue;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EKEYREJECTED;
|
||||
}
|
||||
|
||||
/* Container transformation interface */
|
||||
int adb_c_xfrm(struct adb_xfrm *x, int (*cb)(struct adb_xfrm *, struct adb_block *, struct apk_istream *))
|
||||
{
|
||||
|
|
31
src/adb.h
31
src/adb.h
|
@ -5,10 +5,10 @@
|
|||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include "apk_io.h"
|
||||
#include "apk_trust.h"
|
||||
|
||||
struct adb;
|
||||
struct adb_obj;
|
||||
struct adb_trust;
|
||||
struct adb_verify_ctx;
|
||||
|
||||
typedef uint32_t adb_val_t;
|
||||
|
@ -154,8 +154,8 @@ struct adb_obj {
|
|||
int adb_free(struct adb *);
|
||||
void adb_reset(struct adb *);
|
||||
|
||||
int adb_m_blob(struct adb *, apk_blob_t, struct adb_trust *);
|
||||
int adb_m_map(struct adb *, int fd, uint32_t expected_schema, struct adb_trust *);
|
||||
int adb_m_blob(struct adb *, apk_blob_t, struct apk_trust *);
|
||||
int adb_m_map(struct adb *, int fd, uint32_t expected_schema, struct apk_trust *);
|
||||
#define adb_w_init_alloca(db, schema, num_buckets) adb_w_init_dynamic(db, schema, alloca(sizeof(struct list_head[num_buckets])), num_buckets)
|
||||
#define adb_w_init_tmp(db, size) adb_w_init_static(db, alloca(size), size)
|
||||
int adb_w_init_dynamic(struct adb *db, uint32_t schema, void *buckets, size_t num_buckets);
|
||||
|
@ -216,35 +216,16 @@ int adb_s_field_by_name(const struct adb_object_schema *, const char *);
|
|||
int adb_c_header(struct apk_ostream *os, struct adb *db);
|
||||
int adb_c_block(struct apk_ostream *os, uint32_t type, apk_blob_t);
|
||||
int adb_c_block_copy(struct apk_ostream *os, struct adb_block *b, struct apk_istream *is, struct adb_verify_ctx *);
|
||||
int adb_c_create(struct apk_ostream *os, struct adb *db, struct adb_trust *t);
|
||||
int adb_c_create(struct apk_ostream *os, struct adb *db, struct apk_trust *t);
|
||||
|
||||
/* Trust */
|
||||
#include <openssl/evp.h>
|
||||
|
||||
struct adb_pkey {
|
||||
uint8_t id[16];
|
||||
EVP_PKEY *key;
|
||||
};
|
||||
|
||||
int adb_pkey_init(struct adb_pkey *pkey, EVP_PKEY *key);
|
||||
void adb_pkey_free(struct adb_pkey *pkey);
|
||||
int adb_pkey_load(struct adb_pkey *pkey, int dirfd, const char *fn);
|
||||
|
||||
struct adb_trust {
|
||||
EVP_MD_CTX *mdctx;
|
||||
struct list_head trusted_key_list;
|
||||
struct list_head private_key_list;
|
||||
};
|
||||
|
||||
struct adb_verify_ctx {
|
||||
uint32_t calc;
|
||||
uint8_t sha512[64];
|
||||
};
|
||||
|
||||
int adb_trust_init(struct adb_trust *trust, int keysfd, struct apk_string_array *);
|
||||
void adb_trust_free(struct adb_trust *trust);
|
||||
int adb_trust_write_signatures(struct adb_trust *trust, struct adb *db, struct adb_verify_ctx *vfy, struct apk_ostream *os);
|
||||
int adb_trust_verify_signature(struct adb_trust *trust, struct adb *db, struct adb_verify_ctx *vfy, apk_blob_t sigb);
|
||||
int adb_trust_write_signatures(struct apk_trust *trust, struct adb *db, struct adb_verify_ctx *vfy, struct apk_ostream *os);
|
||||
int adb_trust_verify_signature(struct apk_trust *trust, struct adb *db, struct adb_verify_ctx *vfy, apk_blob_t sigb);
|
||||
|
||||
/* Transform existing file */
|
||||
struct adb_xfrm {
|
||||
|
|
266
src/adb_trust.c
266
src/adb_trust.c
|
@ -1,266 +0,0 @@
|
|||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/err.h>
|
||||
#include "apk_defines.h"
|
||||
#include "adb.h"
|
||||
|
||||
struct adb_trust_key {
|
||||
struct list_head key_node;
|
||||
struct adb_pkey key;
|
||||
|
||||
};
|
||||
|
||||
/* Trust */
|
||||
int adb_pkey_init(struct adb_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 adb_pkey_free(struct adb_pkey *pkey)
|
||||
{
|
||||
EVP_PKEY_free(pkey->key);
|
||||
}
|
||||
|
||||
int adb_pkey_load(struct adb_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;
|
||||
|
||||
adb_pkey_init(pkey, key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct adb_trust_key *adb_trust_load_key(int dirfd, const char *filename)
|
||||
{
|
||||
struct adb_trust_key *key;
|
||||
int r;
|
||||
|
||||
key = calloc(1, sizeof *key);
|
||||
if (!key) return ERR_PTR(-ENOMEM);
|
||||
|
||||
r = adb_pkey_load(&key->key, dirfd, filename);
|
||||
if (r) {
|
||||
free(key);
|
||||
return ERR_PTR(-ENOKEY);
|
||||
}
|
||||
|
||||
list_init(&key->key_node);
|
||||
return key;
|
||||
}
|
||||
|
||||
static int __adb_trust_load_pubkey(void *pctx, int dirfd, const char *filename)
|
||||
{
|
||||
struct adb_trust *trust = pctx;
|
||||
struct adb_trust_key *key = adb_trust_load_key(dirfd, filename);
|
||||
|
||||
if (!IS_ERR(key))
|
||||
list_add_tail(&key->key_node, &trust->trusted_key_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int adb_trust_init(struct adb_trust *trust, int dirfd, struct apk_string_array *pkey_files)
|
||||
{
|
||||
char **fn;
|
||||
|
||||
*trust = (struct adb_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, __adb_trust_load_pubkey, trust);
|
||||
|
||||
foreach_array_item(fn, pkey_files) {
|
||||
struct adb_trust_key *key = adb_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 __adb_trust_free_keys(struct list_head *h)
|
||||
{
|
||||
struct adb_trust_key *tkey, *n;
|
||||
|
||||
list_for_each_entry_safe(tkey, n, h, key_node) {
|
||||
list_del(&tkey->key_node);
|
||||
adb_pkey_free(&tkey->key);
|
||||
free(tkey);
|
||||
}
|
||||
}
|
||||
|
||||
void adb_trust_free(struct adb_trust *trust)
|
||||
{
|
||||
if (!trust->mdctx) return;
|
||||
__adb_trust_free_keys(&trust->trusted_key_list);
|
||||
__adb_trust_free_keys(&trust->private_key_list);
|
||||
EVP_MD_CTX_free(trust->mdctx);
|
||||
}
|
||||
|
||||
static int adb_verify_ctx_calc(struct adb_verify_ctx *vfy, unsigned int hash_alg, apk_blob_t data, apk_blob_t *pmd)
|
||||
{
|
||||
const EVP_MD *evp;
|
||||
apk_blob_t md;
|
||||
|
||||
switch (hash_alg) {
|
||||
case ADB_HASH_SHA512:
|
||||
evp = EVP_sha512();
|
||||
*pmd = md = APK_BLOB_BUF(vfy->sha512);
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (!(vfy->calc & (1 << hash_alg))) {
|
||||
unsigned int sz = md.len;
|
||||
if (APK_BLOB_IS_NULL(data)) return -ENOMSG;
|
||||
if (EVP_Digest(data.ptr, data.len, (unsigned char*) md.ptr, &sz, evp, NULL) != 1 ||
|
||||
sz != md.len)
|
||||
return -EIO;
|
||||
vfy->calc |= (1 << hash_alg);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int adb_trust_write_signatures(struct adb_trust *trust, struct adb *db, struct adb_verify_ctx *vfy, struct apk_ostream *os)
|
||||
{
|
||||
union {
|
||||
struct adb_sign_hdr hdr;
|
||||
struct adb_sign_v0 v0;
|
||||
unsigned char buf[8192];
|
||||
} sig;
|
||||
struct adb_trust_key *tkey;
|
||||
apk_blob_t md;
|
||||
size_t siglen;
|
||||
int r;
|
||||
|
||||
if (!vfy) {
|
||||
vfy = alloca(sizeof *vfy);
|
||||
memset(vfy, 0, sizeof *vfy);
|
||||
}
|
||||
|
||||
r = adb_verify_ctx_calc(vfy, ADB_HASH_SHA512, db->adb, &md);
|
||||
if (r) return r;
|
||||
|
||||
list_for_each_entry(tkey, &trust->private_key_list, key_node) {
|
||||
sig.v0 = (struct adb_sign_v0) {
|
||||
.hdr.sign_ver = 0,
|
||||
.hdr.hash_alg = ADB_HASH_SHA512,
|
||||
};
|
||||
memcpy(sig.v0.id, tkey->key.id, sizeof(sig.v0.id));
|
||||
|
||||
siglen = sizeof sig.buf - sizeof sig.v0;
|
||||
EVP_MD_CTX_set_pkey_ctx(trust->mdctx, NULL);
|
||||
if (EVP_DigestSignInit(trust->mdctx, NULL, EVP_sha512(), NULL, tkey->key.key) != 1 ||
|
||||
EVP_DigestUpdate(trust->mdctx, &db->hdr, sizeof db->hdr) != 1 ||
|
||||
EVP_DigestUpdate(trust->mdctx, &sig.hdr.sign_ver, sizeof sig.hdr.sign_ver) != 1 ||
|
||||
EVP_DigestUpdate(trust->mdctx, &sig.hdr.hash_alg, sizeof sig.hdr.hash_alg) != 1 ||
|
||||
EVP_DigestUpdate(trust->mdctx, md.ptr, md.len) != 1 ||
|
||||
EVP_DigestSignFinal(trust->mdctx, sig.v0.sig, &siglen) != 1) {
|
||||
ERR_print_errors_fp(stdout);
|
||||
goto err_io;
|
||||
}
|
||||
|
||||
r = adb_c_block(os, ADB_BLOCK_SIG, APK_BLOB_PTR_LEN((char*) &sig, sizeof(sig.v0) + siglen));
|
||||
if (r < 0) goto err;
|
||||
}
|
||||
return 0;
|
||||
err_io:
|
||||
r = -EIO;
|
||||
err:
|
||||
apk_ostream_cancel(os, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
int adb_trust_verify_signature(struct adb_trust *trust, struct adb *db, struct adb_verify_ctx *vfy, apk_blob_t sigb)
|
||||
{
|
||||
struct adb_trust_key *tkey;
|
||||
struct adb_sign_hdr *sig;
|
||||
struct adb_sign_v0 *sig0;
|
||||
apk_blob_t md;
|
||||
|
||||
if (APK_BLOB_IS_NULL(db->adb)) return -ENOMSG;
|
||||
if (sigb.len < sizeof(struct adb_sign_hdr)) return -EBADMSG;
|
||||
|
||||
sig = (struct adb_sign_hdr *) sigb.ptr;
|
||||
sig0 = (struct adb_sign_v0 *) sigb.ptr;
|
||||
if (sig->sign_ver != 0) return -ENOSYS;
|
||||
|
||||
list_for_each_entry(tkey, &trust->trusted_key_list, key_node) {
|
||||
if (memcmp(sig0->id, tkey->key.id, sizeof sig0->id) != 0) continue;
|
||||
if (adb_verify_ctx_calc(vfy, sig->hash_alg, db->adb, &md) != 0) continue;
|
||||
|
||||
EVP_MD_CTX_set_pkey_ctx(trust->mdctx, NULL);
|
||||
if (EVP_DigestVerifyInit(trust->mdctx, NULL, EVP_sha512(), NULL, tkey->key.key) != 1 ||
|
||||
EVP_DigestUpdate(trust->mdctx, &db->hdr, sizeof db->hdr) != 1 ||
|
||||
EVP_DigestUpdate(trust->mdctx, &sig->sign_ver, sizeof sig->sign_ver) != 1 ||
|
||||
EVP_DigestUpdate(trust->mdctx, &sig->hash_alg, sizeof sig->hash_alg) != 1 ||
|
||||
EVP_DigestUpdate(trust->mdctx, md.ptr, md.len) != 1 ||
|
||||
EVP_DigestVerifyFinal(trust->mdctx, sig0->sig, sigb.len - sizeof(*sig0)) != 1) {
|
||||
ERR_clear_error();
|
||||
continue;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EKEYREJECTED;
|
||||
}
|
||||
|
||||
/* 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,
|
||||
};
|
|
@ -10,6 +10,7 @@
|
|||
#define APK_CONTEXT_H
|
||||
|
||||
#include "apk_print.h"
|
||||
#include "apk_trust.h"
|
||||
#include "apk_io.h"
|
||||
#include "adb.h"
|
||||
|
||||
|
@ -65,18 +66,17 @@ struct apk_ctx {
|
|||
struct apk_string_array *repository_list;
|
||||
struct apk_string_array *private_keys;
|
||||
|
||||
struct adb_trust trust;
|
||||
struct apk_trust trust;
|
||||
struct apk_id_cache id_cache;
|
||||
struct apk_database *db;
|
||||
int root_fd, keys_fd;
|
||||
int root_fd;
|
||||
};
|
||||
|
||||
void apk_ctx_init(struct apk_ctx *ac);
|
||||
void apk_ctx_free(struct apk_ctx *ac);
|
||||
int apk_ctx_prepare(struct apk_ctx *ac);
|
||||
|
||||
int apk_ctx_fd_keys(struct apk_ctx *ac);
|
||||
struct adb_trust *apk_ctx_get_trust(struct apk_ctx *ac);
|
||||
struct apk_trust *apk_ctx_get_trust(struct apk_ctx *ac);
|
||||
struct apk_id_cache *apk_ctx_get_id_cache(struct apk_ctx *ac);
|
||||
|
||||
static inline int apk_ctx_fd_root(struct apk_ctx *ac) { return ac->root_fd; }
|
||||
|
|
|
@ -129,7 +129,7 @@ struct apk_repository_tag {
|
|||
|
||||
struct apk_database {
|
||||
struct apk_ctx *ctx;
|
||||
int root_fd, lock_fd, cache_fd, keys_fd;
|
||||
int root_fd, lock_fd, cache_fd;
|
||||
unsigned num_repos, num_repo_tags;
|
||||
const char *cache_dir;
|
||||
char *cache_remount_dir, *root_proc_dir;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
struct apk_database;
|
||||
struct apk_name;
|
||||
struct apk_provider;
|
||||
struct apk_trust;
|
||||
|
||||
#define APK_SCRIPT_INVALID -1
|
||||
#define APK_SCRIPT_PRE_INSTALL 0
|
||||
|
@ -45,7 +46,7 @@ struct apk_provider;
|
|||
#define APK_FOREACH_GENID_MASK 0xffffff00
|
||||
|
||||
struct apk_sign_ctx {
|
||||
int keys_fd;
|
||||
struct apk_trust *trust;
|
||||
int action;
|
||||
const EVP_MD *md;
|
||||
int num_signatures;
|
||||
|
@ -132,7 +133,7 @@ APK_ARRAY(apk_package_array, struct apk_package *);
|
|||
extern const char *apk_script_types[];
|
||||
|
||||
void apk_sign_ctx_init(struct apk_sign_ctx *ctx, int action,
|
||||
struct apk_checksum *identity, int keys_fd, int allow_untrusted);
|
||||
struct apk_checksum *identity, struct apk_trust *trust);
|
||||
void apk_sign_ctx_free(struct apk_sign_ctx *ctx);
|
||||
int apk_sign_ctx_process_file(struct apk_sign_ctx *ctx,
|
||||
const struct apk_file_info *fi,
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
struct adb_dump_ctx {
|
||||
struct adb *db;
|
||||
struct adb_trust *trust;
|
||||
struct apk_trust *trust;
|
||||
char prefix[128], *pfx;
|
||||
};
|
||||
|
||||
|
@ -203,7 +203,7 @@ static void dump_adb(struct adb_dump_ctx *ctx)
|
|||
if (IS_ERR(blk)) fprintf(stdout, "%s# block enumeration error: corrupt data area\n", ctx->prefix);
|
||||
}
|
||||
|
||||
static int mmap_and_dump_adb(struct adb_trust *trust, int fd)
|
||||
static int mmap_and_dump_adb(struct apk_trust *trust, int fd)
|
||||
{
|
||||
struct adb db;
|
||||
struct adb_dump_ctx ctx = {
|
||||
|
|
|
@ -41,7 +41,7 @@ static const struct apk_option_group optgroup_applet = {
|
|||
static int update_signatures(struct adb_xfrm *xfrm, struct adb_block *blk, struct apk_istream *is)
|
||||
{
|
||||
struct sign_ctx *ctx = container_of(xfrm, struct sign_ctx, xfrm);
|
||||
struct adb_trust *trust = apk_ctx_get_trust(ctx->ac);
|
||||
struct apk_trust *trust = apk_ctx_get_trust(ctx->ac);
|
||||
int r;
|
||||
|
||||
switch (blk ? ADB_BLOCK_TYPE(blk) : -1) {
|
||||
|
|
|
@ -159,7 +159,7 @@ static int add_main(void *ctx, struct apk_ctx *ac, struct apk_string_array *args
|
|||
return -1;
|
||||
|
||||
apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY_AND_GENERATE,
|
||||
NULL, db->keys_fd, db->ctx->flags & APK_ALLOW_UNTRUSTED);
|
||||
NULL, apk_ctx_get_trust(ac));
|
||||
r = apk_pkg_read(db, *parg, &sctx, &pkg);
|
||||
apk_sign_ctx_free(&sctx);
|
||||
if (r != 0) {
|
||||
|
|
|
@ -52,16 +52,15 @@ static int load_apkindex(void *sctx, const struct apk_file_info *fi,
|
|||
|
||||
static int load_index(struct conv_ctx *ctx, struct apk_istream *is)
|
||||
{
|
||||
struct apk_id_cache *idc = apk_ctx_get_id_cache(ctx->ac);
|
||||
int r = 0;
|
||||
|
||||
if (IS_ERR_OR_NULL(is)) return is ? PTR_ERR(is) : -EINVAL;
|
||||
|
||||
ctx->found = 0;
|
||||
apk_sign_ctx_init(&ctx->sctx, APK_SIGN_VERIFY, NULL, apk_ctx_fd_keys(ctx->ac), ctx->ac->flags & APK_ALLOW_UNTRUSTED);
|
||||
apk_sign_ctx_init(&ctx->sctx, APK_SIGN_VERIFY, NULL, apk_ctx_get_trust(ctx->ac));
|
||||
r = apk_tar_parse(
|
||||
apk_istream_gunzip_mpart(is, apk_sign_ctx_mpart_cb, &ctx->sctx),
|
||||
load_apkindex, ctx, idc);
|
||||
load_apkindex, ctx, apk_ctx_get_id_cache(ctx->ac));
|
||||
apk_sign_ctx_free(&ctx->sctx);
|
||||
if (r >= 0 && ctx->found == 0) r = -ENOMSG;
|
||||
|
||||
|
@ -72,7 +71,7 @@ static int conv_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *ar
|
|||
{
|
||||
char **arg;
|
||||
struct conv_ctx *ctx = pctx;
|
||||
struct adb_trust *trust = apk_ctx_get_trust(ac);
|
||||
struct apk_trust *trust = apk_ctx_get_trust(ac);
|
||||
struct adb_obj ndx;
|
||||
int r;
|
||||
|
||||
|
|
|
@ -186,7 +186,7 @@ static int index_main(void *ctx, struct apk_ctx *ac, struct apk_string_array *ar
|
|||
|
||||
if (!found) {
|
||||
struct apk_sign_ctx sctx;
|
||||
apk_sign_ctx_init(&sctx, ictx->method, NULL, db->keys_fd, db->ctx->flags & APK_ALLOW_UNTRUSTED);
|
||||
apk_sign_ctx_init(&sctx, ictx->method, NULL, apk_ctx_get_trust(ac));
|
||||
r = apk_pkg_read(db, *parg, &sctx, &pkg);
|
||||
if (r < 0) {
|
||||
apk_err(out, "%s: %s", *parg, apk_error_str(r));
|
||||
|
|
|
@ -110,7 +110,7 @@ static void process_file(struct apk_database *db, const char *match)
|
|||
ctx.prefix2 = ": ";
|
||||
}
|
||||
|
||||
apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY, NULL, db->keys_fd, db->ctx->flags & APK_ALLOW_UNTRUSTED);
|
||||
apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY, NULL, apk_ctx_get_trust(db->ctx));
|
||||
r = apk_tar_parse(
|
||||
apk_istream_gunzip_mpart(apk_istream_from_file(AT_FDCWD, match), apk_sign_ctx_mpart_cb, &sctx),
|
||||
read_file_entry, &ctx, idc);
|
||||
|
|
|
@ -190,7 +190,7 @@ static int mkndx_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *a
|
|||
{
|
||||
struct apk_out *out = &ac->out;
|
||||
struct apk_id_cache *idc = apk_ctx_get_id_cache(ac);
|
||||
struct adb_trust *trust = apk_ctx_get_trust(ac);
|
||||
struct apk_trust *trust = apk_ctx_get_trust(ac);
|
||||
struct adb odb, tmpdb;
|
||||
struct adb_obj oroot, opkgs, ndx, tmpl;
|
||||
struct apk_file_info fi;
|
||||
|
@ -276,7 +276,7 @@ static int mkndx_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *a
|
|||
}
|
||||
if (!found) {
|
||||
do_file:
|
||||
apk_sign_ctx_init(&ctx->sctx, APK_SIGN_VERIFY, NULL, apk_ctx_fd_keys(ac), ac->flags & APK_ALLOW_UNTRUSTED);
|
||||
apk_sign_ctx_init(&ctx->sctx, APK_SIGN_VERIFY, NULL, trust);
|
||||
r = apk_tar_parse(
|
||||
apk_istream_gunzip_mpart(apk_istream_from_file(AT_FDCWD, *parg), apk_sign_ctx_mpart_cb, &ctx->sctx),
|
||||
mkndx_parse_v2_tar, ctx, idc);
|
||||
|
|
|
@ -20,11 +20,14 @@ static int verify_main(void *ctx, struct apk_ctx *ac, struct apk_string_array *a
|
|||
struct apk_out *out = &ac->out;
|
||||
struct apk_sign_ctx sctx;
|
||||
struct apk_id_cache *idc = apk_ctx_get_id_cache(ac);
|
||||
struct apk_trust *trust = apk_ctx_get_trust(ac);
|
||||
char **parg;
|
||||
int r, ok, rc = 0;
|
||||
|
||||
trust->allow_untrusted = 1;
|
||||
|
||||
foreach_array_item(parg, args) {
|
||||
apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY, NULL, apk_ctx_fd_keys(ac), 1);
|
||||
apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY, NULL, trust);
|
||||
r = apk_tar_parse(
|
||||
apk_istream_gunzip_mpart(apk_istream_from_file(AT_FDCWD, *parg),
|
||||
apk_sign_ctx_mpart_cb, &sctx),
|
||||
|
|
|
@ -86,7 +86,7 @@ static int option_parse_applet(void *ctx, struct apk_ctx *ac, int opt, const cha
|
|||
break;
|
||||
case OPT_VERSION_check:
|
||||
ictx->action = ver_validate;
|
||||
ac->open_flags |= APK_OPENF_NO_STATE | APK_OPENF_NO_REPOS;
|
||||
ac->open_flags = 0;
|
||||
break;
|
||||
case OPT_VERSION_indexes:
|
||||
ictx->action = ver_indexes;
|
||||
|
@ -96,7 +96,7 @@ static int option_parse_applet(void *ctx, struct apk_ctx *ac, int opt, const cha
|
|||
break;
|
||||
case OPT_VERSION_test:
|
||||
ictx->action = ver_test;
|
||||
ac->open_flags |= APK_OPENF_NO_STATE | APK_OPENF_NO_REPOS;
|
||||
ac->open_flags = 0;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
|
|
|
@ -26,7 +26,7 @@ void apk_ctx_init(struct apk_ctx *ac)
|
|||
void apk_ctx_free(struct apk_ctx *ac)
|
||||
{
|
||||
apk_id_cache_free(&ac->id_cache);
|
||||
adb_trust_free(&ac->trust);
|
||||
apk_trust_free(&ac->trust);
|
||||
apk_string_array_free(&ac->repository_list);
|
||||
apk_string_array_free(&ac->private_keys);
|
||||
}
|
||||
|
@ -55,17 +55,14 @@ int apk_ctx_prepare(struct apk_ctx *ac)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int apk_ctx_fd_keys(struct apk_ctx *ac)
|
||||
{
|
||||
if (ac->keys_fd <= 0) ac->keys_fd = openat(ac->root_fd, ac->keys_dir, O_RDONLY | O_CLOEXEC);
|
||||
return ac->keys_fd;
|
||||
}
|
||||
|
||||
struct adb_trust *apk_ctx_get_trust(struct apk_ctx *ac)
|
||||
struct apk_trust *apk_ctx_get_trust(struct apk_ctx *ac)
|
||||
{
|
||||
if (!ac->trust.mdctx) {
|
||||
int r = adb_trust_init(&ac->trust, dup(apk_ctx_fd_keys(ac)), ac->private_keys);
|
||||
int r = apk_trust_init(&ac->trust,
|
||||
openat(ac->root_fd, ac->keys_dir, O_RDONLY | O_CLOEXEC),
|
||||
ac->private_keys);
|
||||
if (r) return ERR_PTR(r);
|
||||
ac->trust.allow_untrusted = !!(ac->flags & APK_ALLOW_UNTRUSTED);
|
||||
}
|
||||
return &ac->trust;
|
||||
}
|
||||
|
|
|
@ -638,7 +638,7 @@ int apk_cache_download(struct apk_database *db, struct apk_repository *repo,
|
|||
if (cb) cb(cb_ctx, 0);
|
||||
|
||||
if (verify != APK_SIGN_NONE) {
|
||||
apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY, NULL, db->keys_fd, db->ctx->flags & APK_ALLOW_UNTRUSTED);
|
||||
apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY, NULL, apk_ctx_get_trust(db->ctx));
|
||||
is = apk_istream_from_url(url, apk_db_url_since(db, st.st_mtime));
|
||||
is = apk_istream_tee(is, db->cache_fd, tmpcacheitem, !autoupdate, cb, cb_ctx);
|
||||
is = apk_istream_gunzip_mpart(is, apk_sign_ctx_mpart_cb, &sctx);
|
||||
|
@ -1645,8 +1645,6 @@ int apk_db_open(struct apk_database *db, struct apk_ctx *ac)
|
|||
}
|
||||
}
|
||||
|
||||
db->keys_fd = openat(db->root_fd, ac->keys_dir, O_RDONLY | O_CLOEXEC);
|
||||
|
||||
if (db->ctx->flags & APK_OVERLAY_FROM_STDIN) {
|
||||
db->ctx->flags &= ~APK_OVERLAY_FROM_STDIN;
|
||||
apk_db_read_overlay(db, apk_istream_from_fd(STDIN_FILENO));
|
||||
|
@ -1810,7 +1808,6 @@ void apk_db_close(struct apk_database *db)
|
|||
db->cache_remount_dir = NULL;
|
||||
}
|
||||
|
||||
if (db->keys_fd) close(db->keys_fd);
|
||||
if (db->cache_fd) close(db->cache_fd);
|
||||
if (db->lock_fd) close(db->lock_fd);
|
||||
}
|
||||
|
@ -2165,7 +2162,7 @@ static int load_index(struct apk_database *db, struct apk_istream *is,
|
|||
ctx.db = db;
|
||||
ctx.repo = repo;
|
||||
ctx.found = 0;
|
||||
apk_sign_ctx_init(&ctx.sctx, APK_SIGN_VERIFY, NULL, db->keys_fd, db->ctx->flags & APK_ALLOW_UNTRUSTED);
|
||||
apk_sign_ctx_init(&ctx.sctx, APK_SIGN_VERIFY, NULL, apk_ctx_get_trust(db->ctx));
|
||||
r = apk_tar_parse(apk_istream_gunzip_mpart(is, apk_sign_ctx_mpart_cb, &ctx.sctx), load_apkindex, &ctx, db->id_cache);
|
||||
apk_sign_ctx_free(&ctx.sctx);
|
||||
|
||||
|
@ -2793,7 +2790,7 @@ static int apk_db_unpack_pkg(struct apk_database *db,
|
|||
.cb = cb,
|
||||
.cb_ctx = cb_ctx,
|
||||
};
|
||||
apk_sign_ctx_init(&ctx.sctx, APK_SIGN_VERIFY_IDENTITY, &pkg->csum, db->keys_fd, db->ctx->flags & APK_ALLOW_UNTRUSTED);
|
||||
apk_sign_ctx_init(&ctx.sctx, APK_SIGN_VERIFY_IDENTITY, &pkg->csum, apk_ctx_get_trust(db->ctx));
|
||||
r = apk_tar_parse(apk_istream_gunzip_mpart(is, apk_sign_ctx_mpart_cb, &ctx.sctx), apk_db_install_archive_entry, &ctx, db->id_cache);
|
||||
apk_sign_ctx_free(&ctx.sctx);
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
libapk_so_version = '2.99.0'
|
||||
libapk_src = [
|
||||
'adb.c',
|
||||
'adb_trust.c',
|
||||
'apk_adb.c',
|
||||
'atom.c',
|
||||
'blob.c',
|
||||
|
@ -17,6 +16,7 @@ libapk_src = [
|
|||
'package.c',
|
||||
'print.c',
|
||||
'solver.c',
|
||||
'trust.c',
|
||||
'version.c',
|
||||
]
|
||||
|
||||
|
|
|
@ -465,13 +465,12 @@ int apk_script_type(const char *name)
|
|||
}
|
||||
|
||||
void apk_sign_ctx_init(struct apk_sign_ctx *ctx, int action,
|
||||
struct apk_checksum *identity, int keys_fd,
|
||||
int allow_untrusted)
|
||||
struct apk_checksum *identity, struct apk_trust *trust)
|
||||
{
|
||||
memset(ctx, 0, sizeof(struct apk_sign_ctx));
|
||||
ctx->keys_fd = keys_fd;
|
||||
ctx->trust = trust;
|
||||
ctx->action = action;
|
||||
ctx->allow_untrusted = !!allow_untrusted;
|
||||
ctx->allow_untrusted = trust->allow_untrusted;
|
||||
switch (action) {
|
||||
case APK_SIGN_VERIFY:
|
||||
/* If we're only verifing, we're going to start with a
|
||||
|
@ -505,8 +504,6 @@ void apk_sign_ctx_free(struct apk_sign_ctx *ctx)
|
|||
{
|
||||
if (ctx->signature.data.ptr != NULL)
|
||||
free(ctx->signature.data.ptr);
|
||||
if (ctx->signature.pkey != NULL)
|
||||
EVP_PKEY_free(ctx->signature.pkey);
|
||||
EVP_MD_CTX_free(ctx->mdctx);
|
||||
}
|
||||
|
||||
|
@ -539,8 +536,8 @@ int apk_sign_ctx_process_file(struct apk_sign_ctx *ctx,
|
|||
};
|
||||
const EVP_MD *md = NULL;
|
||||
const char *name = NULL;
|
||||
BIO *bio;
|
||||
int r, i, fd;
|
||||
struct apk_pkey *pkey;
|
||||
int r, i;
|
||||
|
||||
if (ctx->data_started)
|
||||
return 1;
|
||||
|
@ -580,9 +577,6 @@ int apk_sign_ctx_process_file(struct apk_sign_ctx *ctx,
|
|||
ctx->signature.pkey != NULL)
|
||||
return 0;
|
||||
|
||||
if (ctx->keys_fd < 0)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(signature_type); i++) {
|
||||
size_t slen = strlen(signature_type[i].type);
|
||||
if (strncmp(&fi->name[6], signature_type[i].type, slen) == 0 &&
|
||||
|
@ -594,17 +588,12 @@ int apk_sign_ctx_process_file(struct apk_sign_ctx *ctx,
|
|||
}
|
||||
if (!md) return 0;
|
||||
|
||||
fd = openat(ctx->keys_fd, name, O_RDONLY|O_CLOEXEC);
|
||||
if (fd < 0) return 0;
|
||||
|
||||
bio = BIO_new_fp(fdopen(fd, "r"), BIO_CLOSE);
|
||||
ctx->signature.pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
|
||||
if (ctx->signature.pkey != NULL) {
|
||||
pkey = apk_trust_key_by_name(ctx->trust, name);
|
||||
if (pkey) {
|
||||
ctx->md = md;
|
||||
ctx->signature.pkey = pkey->key;
|
||||
ctx->signature.data = apk_blob_from_istream(is, fi->size);
|
||||
}
|
||||
BIO_free(bio);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
Loading…
Reference in New Issue