crypto: start seperating public/private key usage

Digests now use bearssl + libsodium instead of openssl + libsodium.
It fits better with the API looking more similar and I don't think it
will be that much of a bottleneck.

Instead of a apk_pkey that mimicks the EVP_PKEY semantics, have seperate
public and private key structures. However, apk is broken because of it
and needs fixing. The rest of the code might compile but won't work
as I haven't handled the cases where pkey corressponds to public/private
keys in codebase properly. Also, DSA signatures are removed.

Public and private keys impls' now use a static array of vtables
internally. The indicies correspond to the signature scheme version and
checking `< APK_*_MAX` should be enough? I tried to make so that higher
values correspond to more desirable constructs, this might come in handy.

Signing/verifying start is free from keys as it isn't used though it
might be brought back for domain seperated hashes, ability to get
timestamps involved with epheremal keys in the future etc.

`apk_crypto.h` is free from openssl includes although some headers still
use them for now.
cute-signatures
Aydin Mercan 2022-08-09 14:17:20 +03:00
parent 2727846361
commit 0b7d6dfbf2
Signed by: jaiden
SSH Key Fingerprint: SHA256:vy6hjzotbn/MWZAbjzURNk3NL62EPkjoHsJ5xr/s7nk
15 changed files with 1055 additions and 627 deletions

View File

@ -18,12 +18,14 @@ shared_deps = [
dependency('zlib'),
dependency('openssl'),
dependency('libsodium'),
dependency('bearssl'),
]
static_deps = [
dependency('openssl', static: true),
dependency('zlib', static: true),
dependency('libsodium', static: true),
dependency('bearssl', static: true),
]
add_project_arguments('-D_GNU_SOURCE', language: 'c')

View File

@ -23,8 +23,8 @@ libapk_soname := 2.99.0
libapk_so := $(obj)/libapk.so.$(libapk_soname)
libapk.so.$(libapk_soname)-objs := \
adb.o adb_comp.o adb_walk_adb.o adb_walk_genadb.o adb_walk_gentext.o adb_walk_text.o apk_adb.o \
atom.o blob.o commit.o common.o context.o crypto_core.o crypto_digest.o crypto_openssl.o database.o hash.o \
extract_v2.o extract_v3.o fs_fsys.o fs_uvol.o io.o io_gunzip.o io_url.o tar.o \
atom.o blob.o commit.o common.o context.o crypto_core.o crypto_digest.o crypto_public.o crypto_secret.o \
database.o hash.o extract_v2.o extract_v3.o fs_fsys.o fs_uvol.o io.o io_gunzip.o io_url.o tar.o \
package.o pathbuilder.o print.o solver.o trust.o version.o
libapk.so.$(libapk_soname)-libs := libfetch/libfetch.a
@ -139,7 +139,8 @@ install: $(obj)/apk $(libapk_so) $(libapk_a) $(apklua_so)
$(install-libapk_a)
$(install-apklua_so)
$(INSTALLDIR) $(DESTDIR)$(INCLUDEDIR)/apk
$(INSTALL) -m644 src/*.h $(DESTDIR)$(INCLUDEDIR)/apk
$(INSTALL) -m644 src/apk_*.h $(DESTDIR)$(INCLUDEDIR)/apk
$(INSTALL) -m644 src/help.h $(DESTDIR)$(INCLUDEDIR)/apk
$(INSTALLDIR) $(DESTDIR)$(PKGCONFIGDIR)
$(INSTALL) -m644 $(obj)/apk.pc $(DESTDIR)$(PKGCONFIGDIR)

View File

@ -1202,10 +1202,20 @@ int adb_trust_write_signatures(struct apk_trust *trust, struct adb *db, struct a
siglen = sizeof sig.buf - sizeof sig.v0;
if ((r = apk_sign_start(&trust->dctx, &tkey->key)) != 0 ||
(r = adb_digest_v0_signature(&trust->dctx, db->schema, &sig.v0, md)) != 0 ||
(r = apk_sign(&trust->dctx, sig.v0.sig, &siglen)) != 0)
r = apk_sign_digest_start(&trust->dctx, tkey->key.version);
if (r != 0) {
goto err;
}
r = adb_digest_v0_signature(&trust->dctx, db->schema, &sig.v0, md);
if (r != 0) {
goto err;
}
r = apk_sign(&tkey->key, &trust->dctx, sig.v0.sig, &siglen);
if (r != 0) {
goto err;
}
r = adb_c_block(os, ADB_BLOCK_SIG, APK_BLOB_PTR_LEN((char*) &sig, sizeof(sig.v0) + siglen));
if (r < 0) goto err;
@ -1234,10 +1244,17 @@ int adb_trust_verify_signature(struct apk_trust *trust, struct adb *db, struct a
if (memcmp(sig0->id, tkey->key.id, sizeof sig0->id) != 0) continue;
if (adb_digest_adb(vfy, sig->hash_alg, db->adb, &md) != 0) continue;
if (apk_verify_start(&trust->dctx, &tkey->key) != 0 ||
adb_digest_v0_signature(&trust->dctx, db->schema, sig0, md) != 0 ||
apk_verify(&trust->dctx, sig0->sig, sigb.len - sizeof *sig0) != 0)
if (apk_verify_digest_start(&trust->dctx, tkey->key.version) != 0) {
continue;
}
if (adb_digest_v0_signature(&trust->dctx, db->schema, sig0, md) != 0) {
continue;
}
if (apk_verify(&tkey->key, &trust->dctx, sig0->sig, sigb.len - sizeof *sig0) != 0) {
continue;
}
return 0;
}

View File

@ -9,20 +9,16 @@
#ifndef APK_CRYPTO_H
#define APK_CRYPTO_H
#include <assert.h>
#include <openssl/evp.h>
#include <string.h>
#include "apk_blob.h"
#include "apk_defines.h"
#include "apk_openssl.h"
// Digest
struct apk_digest_ctx {
uint8_t alg;
void *impl;
EVP_MD_CTX *mdctx;
};
#define APK_DIGEST_NONE 0x00
@ -31,49 +27,31 @@ struct apk_digest_ctx {
#define APK_DIGEST_SHA256 0x03
#define APK_DIGEST_SHA512 0x04
#define APK_DIGEST_SHA256_160 0x05
#define APK_DIGEST_MAX 0x06
#define APK_DIGEST_MAX_LENGTH 64 // longest is SHA512
#define APK_PKEY_ED25519 0x00
#define APK_PKEY_RSAPKCS1v15 0x01
#define APK_KEY_VERSION_V2 0x00
#define APK_KEY_VERSION_CUTE 0x01
#define APK_KEY_VERSION_MAX 0x02
#define APK_PKEY_TYPE_PUBLIC 0x00
#define APK_PKEY_TYPE_SECRET 0x01
#define APK_SIGNATURE_RSA 0x00
#define APK_SIGNATURE_RSA512 0x01
#define APK_SIGNATURE_RSA256 0x02
#define APK_SIGNATURE_CUTE 0x03
#define APK_SIGNATURE_MAX 0x04
// includes '\0'
#define APK_PKEY_CUTE_PUBLIC_SIZE 69
#define APK_PKEY_CUTE_SECRET_SIZE 113
const char *apk_digest_alg_str(uint8_t);
uint8_t apk_digest_alg_from_csum(int);
const char *apk_digest_alg_str(uint8_t alg);
uint8_t apk_digest_alg_from_csum(int csum);
struct apk_digest {
uint8_t alg, len;
uint8_t alg;
uint8_t 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_160:
case APK_DIGEST_SHA256:
return EVP_sha256();
case APK_DIGEST_SHA512:
return EVP_sha512();
default:
assert(alg);
return EVP_md_null();
}
}
int apk_digest_alg_len(uint8_t alg);
uint8_t apk_digest_alg_by_len(int len);
@ -97,25 +75,15 @@ static inline void apk_digest_set(struct apk_digest *d, uint8_t alg)
}
int apk_digest_calc(struct apk_digest *d, uint8_t alg, const void *ptr, size_t sz);
/*
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 -APKE_CRYPTO_ERROR;
d->alg = alg;
d->len = apk_digest_alg_len(alg);
return 0;
}
*/
int apk_digest_ctx_init(struct apk_digest_ctx *dctx, uint8_t alg);
void apk_digest_ctx_reset(struct apk_digest_ctx *dctx, uint8_t alg);
int apk_digest_ctx_reset(struct apk_digest_ctx *dctx, uint8_t alg);
void apk_digest_ctx_free(struct apk_digest_ctx *dctx);
int apk_digest_ctx_update(struct apk_digest_ctx *dctx, const void *ptr, size_t sz);
int apk_digest_ctx_final(struct apk_digest_ctx *dctx, struct apk_digest *d);
uint8_t apk_digest_from_blob(struct apk_digest *d, apk_blob_t b);
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));
@ -132,22 +100,31 @@ static inline void apk_checksum_from_digest(struct apk_checksum *csum, const str
// Asymmetric keys
struct apk_pkey {
uint8_t type;
uint8_t alg;
struct apk_public_key {
uint16_t version;
uint8_t id[16];
void *impl;
};
int apk_pkey_load(struct apk_pkey *pkey, int dirfd, const char *fn);
void apk_pkey_free(struct apk_pkey *pkey);
struct apk_secret_key {
uint16_t version;
uint8_t id[16];
void *impl;
};
int apk_public_key_load(struct apk_public_key *pub, int dirfd, const char *fn);
void apk_public_key_free(struct apk_public_key *pub);
int apk_secret_key_load(struct apk_secret_key *sec, int dirfd, const char *fn);
void apk_secret_key_free(struct apk_secret_key *sec);
// 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);
int apk_sign_digest_start(struct apk_digest_ctx *dctx, uint16_t version);
int apk_sign(struct apk_secret_key *sec, struct apk_digest_ctx *dctx, void *sig, size_t *len);
int apk_verify_digest_start(struct apk_digest_ctx *dctx, uint16_t version);
int apk_verify(struct apk_public_key *pub, struct apk_digest_ctx *dctx, void *sig, size_t len);
// Initializiation

View File

@ -14,9 +14,14 @@
struct apk_trust_key {
struct list_head key_node;
struct apk_pkey key;
struct apk_public_key key;
char *filename;
};
struct apk_trust_secret {
struct list_head key_node;
struct apk_secret_key key;
char *filename;
};
struct apk_trust {
@ -30,6 +35,6 @@ struct apk_trust {
void apk_trust_init(struct apk_trust *trust);
void apk_trust_free(struct apk_trust *trust);
int apk_trust_load_keys(struct apk_trust *trust, int keysfd);
struct apk_pkey *apk_trust_key_by_name(struct apk_trust *trust, const char *filename);
struct apk_public_key *apk_trust_public_key_by_name(struct apk_trust *trust, const char *filename);
#endif

View File

@ -1,24 +1,14 @@
#include <bearssl.h>
#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 tag is in apk_digest_ctx->alg
union digest_state {
crypto_hash_sha256_state sha256;
crypto_hash_sha512_state sha512;
EVP_MD_CTX *mdctx;
br_sha1_context sha1;
br_md5_context md5;
};
static const char *apk_digest_str[] = {
@ -38,8 +28,73 @@ const char *apk_digest_alg_str(uint8_t alg)
return alg_str;
}
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_160:
return 20;
case APK_DIGEST_SHA256:
return 32;
case APK_DIGEST_SHA512:
return 64;
default:
return 0;
}
}
uint8_t apk_digest_alg_by_len(int len)
{
switch (len) {
case 0:
return APK_DIGEST_NONE;
case 16:
return APK_DIGEST_MD5;
case 20:
return APK_DIGEST_SHA1;
case 32:
return APK_DIGEST_SHA256;
case 64:
return APK_DIGEST_SHA512;
default:
return APK_DIGEST_NONE;
}
}
uint8_t apk_digest_alg_from_csum(int csum)
{
switch (csum) {
case APK_CHECKSUM_NONE:
return APK_DIGEST_NONE;
case APK_CHECKSUM_MD5:
return APK_DIGEST_MD5;
case APK_CHECKSUM_SHA1:
return APK_DIGEST_SHA1;
default:
return APK_DIGEST_NONE;
}
}
uint8_t apk_digest_from_blob(struct apk_digest *d, apk_blob_t b)
{
d->alg = apk_digest_alg_by_len(b.len);
d->len = 0;
if (d->alg != APK_DIGEST_NONE) {
d->len = b.len;
memcpy(d->data, b.ptr, d->len);
}
return d->alg;
}
int apk_digest_calc(struct apk_digest *d, uint8_t alg, const void *ptr, size_t sz)
{
union digest_state state;
switch (alg) {
case APK_DIGEST_SHA256:
case APK_DIGEST_SHA256_160:
@ -51,22 +106,28 @@ int apk_digest_calc(struct apk_digest *d, uint8_t alg, const void *ptr, size_t s
case APK_DIGEST_NONE:
break;
case APK_DIGEST_MD5:
br_md5_init(&state.md5);
br_md5_update(&state.md5, ptr, sz);
br_md5_out(&state.md5, d->data);
break;
case APK_DIGEST_SHA1:
br_sha1_init(&state.sha1);
br_sha1_update(&state.sha1, ptr, sz);
br_sha1_out(&state.sha1, d->data);
break;
default:
return -APKE_CRYPTO_NOT_SUPPORTED;
}
d->alg = alg;
d->len = apk_digest_alg_len(d->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;
union digest_state *state;
dctx->impl = malloc(sizeof(union digest_state));
if (dctx->impl == NULL) {
@ -84,49 +145,30 @@ int apk_digest_ctx_init(struct apk_digest_ctx *dctx, uint8_t alg)
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();
br_md5_init(&state->md5);
break;
case APK_DIGEST_SHA1:
evp_md = EVP_sha1();
br_sha1_init(&state->sha1);
break;
case APK_DIGEST_NONE:
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)
int apk_digest_ctx_reset(struct apk_digest_ctx *dctx, uint8_t alg)
{
apk_digest_ctx_free(dctx);
apk_digest_ctx_init(dctx, alg);
return 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;
}
@ -135,19 +177,16 @@ void apk_digest_ctx_free(struct apk_digest_ctx *dctx)
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:
free(dctx->impl);
dctx->impl = NULL;
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)
@ -162,12 +201,13 @@ int apk_digest_ctx_update(struct apk_digest_ctx *dctx, const void *ptr, size_t s
case APK_DIGEST_SHA512:
crypto_hash_sha512_update(&state->sha512, ptr, sz);
break;
case APK_DIGEST_NONE:
case APK_DIGEST_MD5:
br_md5_update(&state->md5, ptr, sz);
break;
case APK_DIGEST_SHA1:
if (EVP_DigestUpdate(state->mdctx, ptr, sz) != 1) {
return -APKE_CRYPTO_ERROR;
}
br_sha1_update(&state->sha1, ptr, sz);
break;
case APK_DIGEST_NONE:
break;
default:
return -APKE_CRYPTO_NOT_SUPPORTED;
@ -178,8 +218,7 @@ int apk_digest_ctx_update(struct apk_digest_ctx *dctx, const void *ptr, size_t s
int apk_digest_ctx_final(struct apk_digest_ctx *dctx, struct apk_digest *d)
{
union digest_state *state = dctx->impl;
unsigned int mdlen;
union digest_state *state = (union digest_state *) dctx->impl;
switch (dctx->alg) {
case APK_DIGEST_SHA256:
@ -189,14 +228,13 @@ int apk_digest_ctx_final(struct apk_digest_ctx *dctx, struct apk_digest *d)
case APK_DIGEST_SHA512:
crypto_hash_sha512_final(&state->sha512, d->data);
break;
case APK_DIGEST_NONE:
case APK_DIGEST_MD5:
br_md5_out(&state->md5, d->data);
break;
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;
}
br_sha1_out(&state->sha1, d->data);
break;
case APK_DIGEST_NONE:
break;
default:
return -APKE_CRYPTO_NOT_SUPPORTED;

View File

@ -1,133 +0,0 @@
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <openssl/bio.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include "apk_crypto.h"
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_160: return 20;
case APK_DIGEST_SHA256: return 32;
case APK_DIGEST_SHA512: return 64;
default: return 0;
}
}
uint8_t apk_digest_alg_by_len(int len)
{
switch (len) {
case 0: return APK_DIGEST_NONE;
case 16: return APK_DIGEST_MD5;
case 20: return APK_DIGEST_SHA1;
case 32: return APK_DIGEST_SHA256;
case 64: return APK_DIGEST_SHA512;
default: return APK_DIGEST_NONE;
}
}
uint8_t apk_digest_alg_from_csum(int csum)
{
switch (csum) {
case APK_CHECKSUM_NONE: return APK_DIGEST_NONE;
case APK_CHECKSUM_MD5: return APK_DIGEST_MD5;
case APK_CHECKSUM_SHA1: return APK_DIGEST_SHA1;
default: return APK_DIGEST_NONE;
}
}
uint8_t apk_digest_from_blob(struct apk_digest *d, apk_blob_t b)
{
d->alg = apk_digest_alg_by_len(b.len);
d->len = 0;
if (d->alg != APK_DIGEST_NONE) {
d->len = b.len;
memcpy(d->data, b.ptr, d->len);
}
return d->alg;
}
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 -APKE_CRYPTO_ERROR;
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) {
(void)BIO_reset(bio);
key = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
}
ERR_clear_error();
BIO_free(bio);
if (!key) return -APKE_CRYPTO_KEY_FORMAT;
apk_pkey_init(pkey, key);
return 0;
}
int apk_sign_start(struct apk_digest_ctx *dctx, struct apk_pkey *pkey)
{
if (EVP_MD_CTX_reset(dctx->mdctx) != 1 ||
EVP_DigestSignInit(dctx->mdctx, NULL, EVP_sha512(), NULL, pkey->key) != 1)
return -APKE_CRYPTO_ERROR;
return 0;
}
int apk_sign(struct apk_digest_ctx *dctx, void *sig, size_t *len)
{
if (EVP_DigestSignFinal(dctx->mdctx, sig, len) != 1) {
ERR_print_errors_fp(stderr);
return -APKE_SIGNATURE_FAIL;
}
return 0;
}
int apk_verify_start(struct apk_digest_ctx *dctx, struct apk_pkey *pkey)
{
if (EVP_MD_CTX_reset(dctx->mdctx) != 1 ||
EVP_DigestVerifyInit(dctx->mdctx, NULL, EVP_sha512(), NULL, pkey->key) != 1)
return -APKE_CRYPTO_ERROR;
return 0;
}
int apk_verify(struct apk_digest_ctx *dctx, void *sig, size_t len)
{
if (EVP_DigestVerifyFinal(dctx->mdctx, sig, len) != 1) {
ERR_print_errors_fp(stderr);
return -APKE_SIGNATURE_INVALID;
}
return 0;
}

350
src/crypto_public.c Normal file
View File

@ -0,0 +1,350 @@
#include <errno.h>
#include <fcntl.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <sodium.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "apk_crypto.h"
/* includes '\0', undef in the end */
#define APK_CUTE_PUBLIC_SIZE 69
union public_key_state {
unsigned char cute[crypto_sign_ed25519_PUBLICKEYBYTES];
EVP_PKEY *pkey;
};
struct public_key_ops {
int (*load)(struct apk_public_key *pub, int fd);
int (*verify)(struct apk_public_key *pub, struct apk_digest_ctx *dctx, void *sig, size_t len);
void (*free)(union public_key_state *state);
};
static int public_key_load_v2(struct apk_public_key *pub, int fd);
static int verify_rsa_pkcs1v15(struct apk_public_key *pub, struct apk_digest_ctx *dctx, void *sig, size_t len);
static void public_key_free_v2(union public_key_state *state);
static int public_key_load_cute(struct apk_public_key *pub, int fd);
static int verify_cute(struct apk_public_key *pub, struct apk_digest_ctx *dctx, void *sig, size_t len);
static void public_key_free_cute(union public_key_state *state);
static const struct public_key_ops ops[] = {
[APK_KEY_VERSION_V2] = {.load = public_key_load_v2, .verify = verify_rsa_pkcs1v15, .free = public_key_free_v2},
[APK_KEY_VERSION_CUTE] = {.load = public_key_load_cute, .verify = verify_cute, .free = public_key_free_cute},
};
/*
* The format is as follows:
* uint8[ 2] header = {'q', 't'}
* uint8[16] key_id
* uint8[32] public_key
*/
static int public_key_load_cute(struct apk_public_key *pub, int fd)
{
union public_key_state *state = (union public_key_state *) pub->impl;
char b64[APK_CUTE_PUBLIC_SIZE];
uint8_t raw[50];
size_t len;
if (read(fd, b64, APK_CUTE_PUBLIC_SIZE) != APK_CUTE_PUBLIC_SIZE) {
return -errno;
}
if (sodium_base642bin(raw, 50, b64, APK_CUTE_PUBLIC_SIZE, NULL, &len, NULL, sodium_base64_VARIANT_ORIGINAL)
!= 0) {
return -APKE_CRYPTO_KEY_FORMAT;
}
if (len != 50) {
return -APKE_CRYPTO_KEY_FORMAT;
}
if (raw[0] != 'q' || raw[1] != 't') {
return -APKE_CRYPTO_KEY_FORMAT;
}
memcpy(pub->id, raw + 2, sizeof pub->id);
memcpy(state->cute, raw + 18, crypto_sign_ed25519_PUBLICKEYBYTES);
return 0;
}
/*
* The signature format is as follows:
* uint8[ 2] header = {'q', 't'}
* uint8[16] key_id
* uint8[64] signature
*/
static int verify_cute(struct apk_public_key *pub, struct apk_digest_ctx *dctx, void *sig, size_t len)
{
union public_key_state *state = (union public_key_state *) pub->impl;
unsigned char *sigdata = (unsigned char *) sig;
struct apk_digest digest;
if (len != 82) {
return -APKE_SIGNATURE_INVALID;
}
if (sigdata[0] != 'q' || sigdata[1] != 't') {
return -APKE_SIGNATURE_INVALID;
}
if (sodium_memcmp(pub->id, sigdata + 2, sizeof pub->id) != 0) {
return -APKE_SIGNATURE_INVALID;
}
if (dctx->alg != APK_DIGEST_SHA256) {
return -APKE_SIGNATURE_INVALID;
}
if (apk_digest_ctx_final(dctx, &digest) != 0) {
return -APKE_SIGNATURE_INVALID;
}
if (crypto_sign_ed25519_verify_detached(sigdata + 18, digest.data, digest.len, state->cute) != 0) {
return -APKE_SIGNATURE_INVALID;
}
return 0;
}
static void public_key_free_cute(union public_key_state *state)
{
return;
}
static int public_key_load_v2(struct apk_public_key *pub, int fd)
{
union public_key_state *state = (union public_key_state *) pub->impl;
unsigned char *raw = NULL;
struct apk_digest digest;
BIO *bio;
int len;
int r = -APKE_CRYPTO_KEY_FORMAT;
bio = BIO_new_fd(fd, BIO_NOCLOSE);
if (bio == NULL) {
r = -ENOMEM;
goto err_bio_new;
}
state->pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
if (state->pkey == NULL) {
r = -APKE_CRYPTO_KEY_FORMAT;
goto err_load_and_check_type;
}
if (state->pkey == NULL) {
r = -APKE_CRYPTO_KEY_FORMAT;
goto err_load_and_check_type;
}
if (EVP_PKEY_id(state->pkey) != EVP_PKEY_RSA) {
r = -APKE_CRYPTO_KEY_FORMAT;
goto err_load_and_check_type;
}
len = i2d_PublicKey(state->pkey, &raw);
if (len < 0) {
r = -APKE_CRYPTO_ERROR;
goto err_load_and_check_type;
}
if (apk_digest_calc(&digest, APK_DIGEST_SHA512, raw, len) != 0) {
r = -APKE_CRYPTO_ERROR;
goto err_calculate_id;
}
memcpy(pub->id, digest.data, sizeof pub->id);
r = 0;
err_calculate_id:
OPENSSL_free(raw);
err_load_and_check_type:
BIO_free(bio);
err_bio_new:
return r;
}
/*
* RSA-PKCS1 v1.5 can work with different hashes.
* Since APK v2 hasn't switched from SHA-1 yet, we still have to work with it for now.
* However, MD5 is out of the question.
*/
static int verify_rsa_pkcs1v15(struct apk_public_key *pub, struct apk_digest_ctx *dctx, void *sig, size_t len)
{
union public_key_state *state = (union public_key_state *) pub->impl;
struct apk_digest digest;
EVP_PKEY_CTX *pctx;
const EVP_MD *md;
int r = -APKE_SIGNATURE_INVALID;
if (apk_digest_ctx_final(dctx, &digest) != 0) {
r = -APKE_SIGNATURE_INVALID;
goto err_digest_final_and_pctx_new;
}
switch (dctx->alg) {
case APK_DIGEST_SHA1:
md = EVP_sha1();
break;
case APK_DIGEST_SHA256:
md = EVP_sha256();
break;
case APK_DIGEST_SHA512:
md = EVP_sha512();
break;
case APK_DIGEST_NONE:
case APK_DIGEST_MD5:
default:
r = -APKE_SIGNATURE_INVALID;
goto err_digest_final_and_pctx_new;
}
pctx = EVP_PKEY_CTX_new(state->pkey, NULL);
if (pctx == NULL) {
r = -APKE_SIGNATURE_INVALID;
goto err_pctx_setup_and_verify;
}
if (EVP_PKEY_verify_init(pctx) != 1) {
r = -APKE_SIGNATURE_INVALID;
goto err_pctx_setup_and_verify;
}
if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PADDING) != 1) {
r = -APKE_SIGNATURE_INVALID;
goto err_pctx_setup_and_verify;
}
if (EVP_PKEY_CTX_set_signature_md(pctx, md) != 1) {
r = -APKE_SIGNATURE_INVALID;
goto err_pctx_setup_and_verify;
}
if (EVP_PKEY_verify(pctx, sig, len, digest.data, digest.len) != 1) {
r = -APKE_SIGNATURE_INVALID;
goto err_pctx_setup_and_verify;
}
r = 0;
err_pctx_setup_and_verify:
EVP_PKEY_CTX_free(pctx);
err_digest_final_and_pctx_new:
return r;
}
static void public_key_free_v2(union public_key_state *state)
{
EVP_PKEY_free(state->pkey);
}
int apk_public_key_load(struct apk_public_key *pub, int dirfd, const char *fn)
{
struct stat st;
int fd = -1;
int r = -APKE_CRYPTO_KEY_FORMAT;
pub->impl = malloc(sizeof(union public_key_state));
if (pub->impl == NULL) {
r = -ENOMEM;
goto err_alloc;
}
fd = openat(dirfd, fn, O_RDONLY | O_CLOEXEC);
if (fd == -1) {
r = -errno;
goto err_openat;
}
if (fstat(fd, &st) != 0) {
r = -errno;
goto err_fstat_and_load;
}
// guess
if (st.st_size == APK_CUTE_PUBLIC_SIZE) {
pub->version = APK_KEY_VERSION_CUTE;
} else {
pub->version = APK_KEY_VERSION_V2;
}
r = ops[pub->version].load(pub, fd);
if (r != 0) {
goto err_fstat_and_load;
}
close(fd);
return 0;
err_fstat_and_load:
close(fd);
err_openat:
free(pub->impl);
err_alloc:
return r;
}
void apk_public_key_free(struct apk_public_key *pub)
{
if (pub == NULL) {
return;
}
if (pub->impl == NULL || pub->version >= APK_KEY_VERSION_MAX) {
return;
}
ops[pub->version].free(pub->impl);
free(pub->impl);
pub->impl = NULL;
}
int apk_verify_digest_start(struct apk_digest_ctx *dctx, uint16_t signature_type)
{
uint8_t digest;
switch (signature_type) {
case APK_SIGNATURE_CUTE:
case APK_SIGNATURE_RSA256:
digest = APK_DIGEST_SHA256;
break;
case APK_SIGNATURE_RSA512:
digest = APK_DIGEST_SHA512;
break;
case APK_SIGNATURE_RSA:
digest = APK_DIGEST_SHA1;
break;
default:
return -APKE_CRYPTO_NOT_SUPPORTED;
}
if (apk_digest_ctx_reset(dctx, digest) != 0) {
return -APKE_CRYPTO_ERROR;
}
return 0;
}
int apk_verify(struct apk_public_key *pub, struct apk_digest_ctx *dctx, void *sig, size_t len)
{
if (pub->version >= APK_KEY_VERSION_MAX) {
return -APKE_CRYPTO_NOT_SUPPORTED;
}
return ops[pub->version].verify(pub, dctx, sig, len);
}
#undef APK_CUTE_PUBLIC_SIZE

347
src/crypto_secret.c Normal file
View File

@ -0,0 +1,347 @@
#include <errno.h>
#include <fcntl.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <sodium.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "apk_crypto.h"
/* includes '\0', undef in the end */
#define APK_CUTE_SECRET_SIZE 113
union secret_key_state {
unsigned char cute[crypto_sign_ed25519_SECRETKEYBYTES];
EVP_PKEY *pkey;
};
struct secret_key_ops {
int (*load)(struct apk_secret_key *pub, int fd);
int (*sign)(struct apk_secret_key *pub, struct apk_digest_ctx *dctx, void *sig, size_t *len);
void (*free)(union secret_key_state *state);
};
static int secret_key_load_v2(struct apk_secret_key *pub, int fd);
static int sign_rsa_pkcs1v15(struct apk_secret_key *pub, struct apk_digest_ctx *dctx, void *sig, size_t *len);
static void secret_key_free_v2(union secret_key_state *state);
static int secret_key_load_cute(struct apk_secret_key *pub, int fd);
static int sign_cute(struct apk_secret_key *pub, struct apk_digest_ctx *dctx, void *sig, size_t *len);
static void secret_key_free_cute(union secret_key_state *state);
static struct secret_key_ops ops[] = {
[APK_KEY_VERSION_CUTE] = {.load = secret_key_load_cute, .sign = sign_cute, .free = secret_key_free_cute},
[APK_KEY_VERSION_V2] = {.load = secret_key_load_v2, .sign = sign_rsa_pkcs1v15, .free = secret_key_free_v2},
};
/*
* The format is as follows:
* uint8[ 2] header = {'q', 't'}
* uint8[16] key_id
* uint8[64] secret_key
*
*/
static int secret_key_load_cute(struct apk_secret_key *sec, int fd)
{
union secret_key_state *state = (union secret_key_state *) sec->impl;
char b64[APK_CUTE_SECRET_SIZE];
uint8_t raw[82];
size_t len;
int r = -APKE_CRYPTO_KEY_FORMAT;
if (read(fd, b64, APK_CUTE_SECRET_SIZE) != APK_CUTE_SECRET_SIZE) {
r = -errno;
goto err;
}
if (sodium_base642bin(raw, 82, b64, APK_CUTE_SECRET_SIZE, NULL, &len, NULL, sodium_base64_VARIANT_ORIGINAL)
!= 0) {
r = -APKE_CRYPTO_KEY_FORMAT;
goto err;
}
if (raw[0] != 'q' || raw[1] != 't') {
r = -APKE_CRYPTO_KEY_FORMAT;
goto err;
}
sec->version = APK_KEY_VERSION_V2;
memcpy(sec->id, raw + 2, 16);
memcpy(state->cute, raw + 18, crypto_sign_ed25519_SECRETKEYBYTES);
r = 0;
err:
sodium_memzero(b64, sizeof b64);
sodium_memzero(raw, sizeof raw);
return r;
}
static void secret_key_free_cute(union secret_key_state *state)
{
sodium_memzero(state->cute, crypto_sign_ed25519_SECRETKEYBYTES);
}
static int sign_cute(struct apk_secret_key *sec, struct apk_digest_ctx *dctx, void *sig, size_t *len)
{
union secret_key_state *state = (union secret_key_state *) sec->impl;
unsigned char *sigdata = (unsigned char *) sig;
struct apk_digest digest;
if (*len < 82) {
return -APKE_SIGNATURE_FAIL;
}
if (dctx->alg != APK_DIGEST_SHA256) {
return -APKE_SIGNATURE_FAIL;
}
if (apk_digest_ctx_final(dctx, &digest) != 0) {
return -APKE_SIGNATURE_FAIL;
}
sigdata[0] = 'q';
sigdata[1] = 't';
memcpy(sigdata + 2, sec->id, 16);
crypto_sign_ed25519_detached(sigdata + 18, NULL, digest.data, digest.len, state->cute);
*len = 82;
return 0;
}
static int secret_key_load_v2(struct apk_secret_key *sec, int fd)
{
union secret_key_state *state = (union secret_key_state *) sec->impl;
struct apk_digest digest;
unsigned char *raw = NULL;
BIO *bio;
int len;
int r = -APKE_CRYPTO_KEY_FORMAT;
bio = BIO_new_fd(fd, BIO_NOCLOSE);
if (bio == NULL) {
r = -ENOMEM;
goto err_bio_new;
}
state->pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
if (state->pkey == NULL) {
r = -APKE_CRYPTO_KEY_FORMAT;
goto err_load_and_check_type;
}
if (EVP_PKEY_id(state->pkey) != EVP_PKEY_RSA) {
r = -APKE_CRYPTO_KEY_FORMAT;
goto err_load_and_check_type;
}
len = i2d_PublicKey(state->pkey, &raw);
if (len < 0) {
r = -APKE_CRYPTO_ERROR;
goto err_load_and_check_type;
}
if (apk_digest_calc(&digest, APK_DIGEST_SHA512, raw, len) != 0) {
r = -APKE_CRYPTO_ERROR;
goto err_digest;
}
memcpy(sec->id, digest.data, sizeof sec->id);
r = 0;
err_digest:
OPENSSL_free(raw);
err_load_and_check_type:
BIO_free(bio);
err_bio_new:
return r;
}
static int sign_rsa_pkcs1v15(struct apk_secret_key *sec, struct apk_digest_ctx *dctx, void *sig, size_t *len)
{
union secret_key_state *state = (union secret_key_state *) sec->impl;
struct apk_digest digest;
EVP_PKEY_CTX *pctx;
const EVP_MD *md;
int r = -APKE_SIGNATURE_FAIL;
size_t needed;
if (apk_digest_ctx_final(dctx, &digest) != 0) {
r = -APKE_SIGNATURE_FAIL;
goto err_digest_final_and_pctx_new;
}
switch (dctx->alg) {
case APK_DIGEST_SHA1:
md = EVP_sha1();
break;
case APK_DIGEST_SHA256:
md = EVP_sha256();
break;
case APK_DIGEST_SHA512:
md = EVP_sha512();
break;
case APK_DIGEST_NONE:
case APK_DIGEST_MD5:
default:
r = -APKE_SIGNATURE_FAIL;
goto err_digest_final_and_pctx_new;
}
pctx = EVP_PKEY_CTX_new(state->pkey, NULL);
if (pctx == NULL) {
r = -APKE_SIGNATURE_FAIL;
goto err_digest_final_and_pctx_new;
}
if (EVP_PKEY_sign_init(pctx) != 1) {
r = -APKE_SIGNATURE_FAIL;
goto err_pctx_setup_and_sign;
}
if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PADDING) != 1) {
r = -APKE_SIGNATURE_FAIL;
goto err_pctx_setup_and_sign;
}
if (EVP_PKEY_CTX_set_signature_md(pctx, md) != 1) {
r = -APKE_SIGNATURE_INVALID;
goto err_pctx_setup_and_sign;
}
/* Determine minimum required buffer size */
if (EVP_PKEY_sign(pctx, NULL, &needed, digest.data, digest.len) != 1) {
r = -APKE_SIGNATURE_FAIL;
goto err_pctx_setup_and_sign;
}
if (needed < *len) {
r = -APKE_SIGNATURE_FAIL;
goto err_pctx_setup_and_sign;
}
if (EVP_PKEY_sign(pctx, sig, len, digest.data, digest.len) != 1) {
r = -APKE_SIGNATURE_FAIL;
goto err_pctx_setup_and_sign;
}
r = 0;
err_pctx_setup_and_sign:
EVP_PKEY_CTX_free(pctx);
err_digest_final_and_pctx_new:
return r;
}
static void secret_key_free_v2(union secret_key_state *state)
{
EVP_PKEY_free(state->pkey);
}
int apk_secret_key_load(struct apk_secret_key *sec, int dirfd, const char *fn)
{
struct stat st;
int fd = -1;
int r = -APKE_CRYPTO_KEY_FORMAT;
sec->impl = malloc(sizeof(union secret_key_state));
if (sec->impl == NULL) {
r = -ENOMEM;
goto err_alloc;
}
fd = openat(dirfd, fn, O_RDONLY | O_CLOEXEC);
if (fd == -1) {
r = -errno;
goto err_openat;
}
if (fstat(fd, &st) != 0) {
r = -errno;
goto err_fstat;
}
if (st.st_size == APK_CUTE_SECRET_SIZE) {
sec->version = APK_KEY_VERSION_CUTE;
} else {
sec->version = APK_KEY_VERSION_V2;
}
r = ops[sec->version].load(sec, fd);
if (r != 0) {
goto err_load;
}
close(fd);
return 0;
err_load:
err_fstat:
close(fd);
err_openat:
free(sec->impl);
err_alloc:
return r;
}
void apk_secret_key_free(struct apk_secret_key *sec)
{
if (sec == NULL) {
return;
}
if (sec->impl == NULL || sec->version >= APK_KEY_VERSION_MAX) {
return;
}
ops[sec->version].free(sec->impl);
free(sec->impl);
sec->impl = NULL;
}
int apk_sign_digest_start(struct apk_digest_ctx *dctx, uint16_t signature_type)
{
uint8_t digest;
switch (signature_type) {
case APK_SIGNATURE_CUTE:
case APK_SIGNATURE_RSA256:
digest = APK_DIGEST_SHA256;
break;
case APK_SIGNATURE_RSA512:
digest = APK_DIGEST_SHA512;
break;
case APK_SIGNATURE_RSA:
digest = APK_DIGEST_SHA1;
break;
default:
return -APKE_CRYPTO_NOT_SUPPORTED;
}
if (apk_digest_ctx_reset(dctx, digest) != 0) {
return -APKE_CRYPTO_ERROR;
}
return 0;
}
int apk_sign(struct apk_secret_key *sec, struct apk_digest_ctx *dctx, void *sig, size_t *len)
{
if (sec->version >= APK_KEY_VERSION_MAX) {
return -APKE_CRYPTO_NOT_SUPPORTED;
}
return ops[sec->version].sign(sec, dctx, sig, len);
}
#undef APK_CUTE_SECRET_SIZE

View File

@ -1,232 +0,0 @@
#include <fcntl.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <sodium.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "apk_crypto.h"
union pkey_state {
unsigned char cute_pk[crypto_sign_ed25519_PUBLICKEYBYTES];
unsigned char cute_sk[crypto_sign_ed25519_SECRETKEYBYTES];
EVP_PKEY *pkey;
};
static int load_openssl(int fd, struct apk_pkey *pkey)
{
int r = -APKE_CRYPTO_KEY_FORMAT;
union pkey_state *state;
BIO *bio;
pkey->impl = malloc(sizeof(union pkey_state));
if (pkey->impl == NULL) {
r = -ENOMEM;
goto err_alloc;
}
bio = BIO_new_fd(fd, BIO_NOCLOSE);
if (bio == NULL) {
r = -ENOMEM;
goto err_bio_new;
}
state = (union pkey_state *) pkey->impl;
pkey->type = APK_PKEY_TYPE_PUBLIC;
state->pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
if (state->pkey == NULL) {
pkey->type = APK_PKEY_TYPE_SECRET;
BIO_reset(bio);
state->pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
}
ERR_clear_error();
if (state->pkey == NULL) {
r = -APKE_CRYPTO_KEY_FORMAT;
goto err_load;
}
BIO_free(bio);
return 0;
err_load:
BIO_free(bio);
err_bio_new:
free(pkey->impl);
err_alloc:
return r;
}
static int load_public_cute(int fd, struct apk_pkey *pkey)
{
char b64[APK_PKEY_CUTE_PUBLIC_SIZE];
int r = -APKE_CRYPTO_KEY_FORMAT;
union pkey_state *state;
uint8_t raw[50]; // 2 + 16 + 32
size_t len;
pkey->impl = malloc(sizeof(union pkey_state));
if (pkey->impl == NULL) {
r = -ENOMEM;
goto err_alloc;
}
state = (union pkey_state *) pkey->impl;
if (read(fd, b64, APK_PKEY_CUTE_PUBLIC_SIZE) != APK_PKEY_CUTE_PUBLIC_SIZE) {
r = -APKE_CRYPTO_KEY_FORMAT;
goto err_read;
}
if (sodium_base642bin(raw,
50,
b64,
APK_PKEY_CUTE_PUBLIC_SIZE,
NULL,
&len,
NULL,
sodium_base64_VARIANT_URLSAFE)
!= 0) {
r = -APKE_CRYPTO_KEY_FORMAT;
goto err_b64decode;
}
if (raw[0] != 'q' || raw[1] != 't') {
r = -APKE_CRYPTO_KEY_FORMAT;
goto err_rawheader;
}
pkey->type = APK_PKEY_TYPE_PUBLIC;
pkey->alg = APK_PKEY_ED25519;
memcpy(pkey->id, raw + 2, 16);
memcpy(state->cute_pk, raw + 18, crypto_sign_ed25519_PUBLICKEYBYTES);
return 0;
err_rawheader:
err_b64decode:
err_read:
free(pkey->impl);
err_alloc:
return r;
}
static int load_secret_cute(int fd, struct apk_pkey *pkey)
{
char b64[APK_PKEY_CUTE_SECRET_SIZE];
int r = -APKE_CRYPTO_KEY_FORMAT;
union pkey_state *state;
uint8_t raw[82]; // 2 + 16 + 64
size_t len;
pkey->impl = malloc(sizeof(union pkey_state));
if (pkey->impl == NULL) {
r = -ENOMEM;
goto err_alloc;
}
state = (union pkey_state *) pkey->impl;
if (read(fd, b64, APK_PKEY_CUTE_SECRET_SIZE) != APK_PKEY_CUTE_SECRET_SIZE) {
r = -APKE_CRYPTO_KEY_FORMAT;
goto err_read;
}
if (sodium_base642bin(raw,
82,
b64,
APK_PKEY_CUTE_PUBLIC_SIZE,
NULL,
&len,
NULL,
sodium_base64_VARIANT_URLSAFE)
!= 0) {
r = -APKE_CRYPTO_KEY_FORMAT;
goto err_b64decode;
}
if (len != 82) {
r = -APKE_CRYPTO_KEY_FORMAT;
goto err_decodelen;
}
if (raw[0] != 'q' || raw[1] != 't') {
r = -APKE_CRYPTO_KEY_FORMAT;
goto err_rawheader;
}
pkey->type = APK_PKEY_TYPE_SECRET;
pkey->alg = APK_PKEY_ED25519;
memcpy(pkey->id, raw + 2, 16);
memcpy(state->cute_sk, raw + 18, crypto_sign_ed25519_SECRETKEYBYTES);
return 0;
err_rawheader:
err_decodelen:
err_b64decode:
err_read:
free(pkey->impl);
err_alloc:
return r;
}
void apk_pkey_free(struct apk_pkey *pkey)
{
union pkey_state *state = (union pkey_state *) pkey->impl;
switch (pkey->alg) {
case APK_PKEY_ED25519:
break;
case APK_PKEY_RSAPKCS1v15:
EVP_PKEY_free(state->pkey);
break;
default:
/* invalid state, don't touch impl */
return;
}
free(pkey->impl);
pkey->impl = NULL;
}
int apk_pkey_load(struct apk_pkey *pkey, int dirfd, const char *fn)
{
struct stat st;
int fd, r = 0;
fd = openat(dirfd, fn, O_RDONLY | O_CLOEXEC);
if (fd == -1) {
r = -errno;
goto err_openat;
}
if (fstat(fd, &st) != 0) {
r = -errno;
goto err_fstat;
}
switch (st.st_size) {
case APK_PKEY_CUTE_SECRET_SIZE:
r = load_secret_cute(fd, pkey);
break;
case APK_PKEY_CUTE_PUBLIC_SIZE:
r = load_public_cute(fd, pkey);
break;
default:
r = load_openssl(fd, pkey);
break;
}
err_fstat:
close(fd);
err_openat:
return r;
}

View File

@ -7,19 +7,20 @@
* SPDX-License-Identifier: GPL-2.0-only
*/
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <fnmatch.h>
#include <libgen.h>
#include <limits.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <fnmatch.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/file.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#ifdef __linux__
# include <mntent.h>

View File

@ -8,20 +8,20 @@
*/
#include "apk_context.h"
#include "apk_crypto.h"
#include "apk_extract.h"
#include "apk_package.h"
#include "apk_tar.h"
#define APK_SIGN_NONE 0
#define APK_SIGN_VERIFY 1
#define APK_SIGN_VERIFY_IDENTITY 2
#define APK_SIGN_GENERATE 4
#define APK_SIGN_VERIFY_AND_GENERATE 5
#define APK_SIGN_NONE 0
#define APK_SIGN_VERIFY 1
#define APK_SIGN_VERIFY_IDENTITY 2
#define APK_SIGN_GENERATE 4
#define APK_SIGN_VERIFY_AND_GENERATE 5
struct apk_sign_ctx {
struct apk_trust *trust;
int action;
const EVP_MD *md;
int num_signatures;
int control_started : 1;
int data_started : 1;
@ -29,57 +29,65 @@ struct apk_sign_ctx {
int control_verified : 1;
int data_verified : 1;
int allow_untrusted : 1;
char data_checksum[EVP_MAX_MD_SIZE];
char data_checksum[APK_DIGEST_MAX_LENGTH];
struct apk_checksum identity;
EVP_MD_CTX *mdctx;
struct apk_digest_ctx digest_ctx;
struct {
struct apk_public_key *public_key;
apk_blob_t data;
EVP_PKEY *pkey;
uint16_t type;
char *identity;
} signature;
};
static void apk_sign_ctx_init(struct apk_sign_ctx *ctx, int action, struct apk_checksum *identity, struct apk_trust *trust)
static void
apk_sign_ctx_init(struct apk_sign_ctx *ctx, int action, struct apk_checksum *identity, struct apk_trust *trust)
{
uint8_t digest_alg;
memset(ctx, 0, sizeof(struct apk_sign_ctx));
ctx->trust = trust;
ctx->action = action;
ctx->trust = trust;
ctx->action = action;
ctx->allow_untrusted = trust->allow_untrusted;
switch (action) {
case APK_SIGN_VERIFY:
/* If we're only verifing, we're going to start with a
* signature section, which we don't need a hash of */
ctx->md = EVP_md_null();
digest_alg = APK_DIGEST_NONE;
break;
case APK_SIGN_VERIFY_IDENTITY:
/* If we're checking the package against a particular hash,
* we need to start with that hash, because there may not
* be a signature section to deduce it from */
ctx->md = EVP_sha1();
digest_alg = APK_DIGEST_SHA1;
memcpy(&ctx->identity, identity, sizeof(ctx->identity));
break;
case APK_SIGN_GENERATE:
case APK_SIGN_VERIFY_AND_GENERATE:
ctx->md = EVP_sha1();
digest_alg = APK_DIGEST_SHA1;
break;
default:
ctx->action = APK_SIGN_NONE;
ctx->md = EVP_md_null();
ctx->action = APK_SIGN_NONE;
ctx->control_started = 1;
ctx->data_started = 1;
ctx->data_started = 1;
digest_alg = APK_DIGEST_NONE;
break;
}
ctx->mdctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(ctx->mdctx, ctx->md, NULL);
EVP_MD_CTX_set_flags(ctx->mdctx, EVP_MD_CTX_FLAG_ONESHOT);
apk_digest_ctx_init(&ctx->digest_ctx, digest_alg);
}
static void apk_sign_ctx_free(struct apk_sign_ctx *ctx)
{
if (ctx->signature.data.ptr != NULL)
if (ctx->signature.data.ptr != NULL) {
free(ctx->signature.data.ptr);
EVP_MD_CTX_free(ctx->mdctx);
}
apk_public_key_free(ctx->signature.public_key);
}
static int check_signing_key_trust(struct apk_sign_ctx *sctx)
@ -87,55 +95,63 @@ static int check_signing_key_trust(struct apk_sign_ctx *sctx)
switch (sctx->action) {
case APK_SIGN_VERIFY:
case APK_SIGN_VERIFY_AND_GENERATE:
if (sctx->signature.pkey == NULL) {
if (sctx->allow_untrusted)
if (sctx->signature.public_key == NULL) {
if (sctx->allow_untrusted) {
break;
}
return -APKE_SIGNATURE_UNTRUSTED;
}
}
return 0;
}
static int apk_sign_ctx_process_file(struct apk_sign_ctx *ctx, const struct apk_file_info *fi,
struct apk_istream *is)
static int apk_sign_ctx_process_file(struct apk_sign_ctx *ctx, const struct apk_file_info *fi, struct apk_istream *is)
{
static struct {
char type[8];
unsigned int nid;
uint8_t alg;
} signature_type[] = {
{ "RSA512", NID_sha512 },
{ "RSA256", NID_sha256 },
{ "RSA", NID_sha1 },
{ "DSA", NID_dsa },
{"RSA256", APK_SIGNATURE_RSA256},
{"RSA512", APK_SIGNATURE_RSA512},
{"CUTE", APK_SIGNATURE_CUTE},
{"RSA", APK_SIGNATURE_RSA},
};
const EVP_MD *md = NULL;
uint16_t signature_alg = APK_SIGNATURE_MAX;
struct apk_public_key *public_key;
const char *name = NULL;
struct apk_pkey *pkey;
int r, i;
if (ctx->data_started)
if (ctx->data_started) {
return 1;
}
if (fi->name[0] != '.' || strchr(fi->name, '/') != NULL) {
/* APKv1.0 compatibility - first non-hidden file is
* considered to start the data section of the file.
* This does not make any sense if the file has v2.0
* style .PKGINFO */
if (ctx->has_data_checksum)
if (ctx->has_data_checksum) {
return -APKE_V2PKG_FORMAT;
}
/* Error out early if identity part is missing */
if (ctx->action == APK_SIGN_VERIFY_IDENTITY)
if (ctx->action == APK_SIGN_VERIFY_IDENTITY) {
return -APKE_V2PKG_FORMAT;
ctx->data_started = 1;
}
ctx->data_started = 1;
ctx->control_started = 1;
r = check_signing_key_trust(ctx);
if (r < 0)
if (r < 0) {
return r;
}
return 1;
}
if (ctx->control_started)
if (ctx->control_started) {
return 1;
}
if (strncmp(fi->name, ".SIGN.", 6) != 0) {
ctx->control_started = 1;
@ -146,32 +162,36 @@ static int apk_sign_ctx_process_file(struct apk_sign_ctx *ctx, const struct apk_
ctx->num_signatures++;
/* Already found a signature by a trusted key; no need to keep searching */
if ((ctx->action != APK_SIGN_VERIFY &&
ctx->action != APK_SIGN_VERIFY_AND_GENERATE) ||
ctx->signature.pkey != NULL)
if ((ctx->action != APK_SIGN_VERIFY && ctx->action != APK_SIGN_VERIFY_AND_GENERATE)
|| ctx->signature.public_key != NULL)
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 &&
fi->name[6+slen] == '.') {
md = EVP_get_digestbynid(signature_type[i].nid);
name = &fi->name[6+slen+1];
if (strncmp(&fi->name[6], signature_type[i].type, slen) == 0 && fi->name[6 + slen] == '.') {
signature_alg = signature_type[i].alg;
name = &fi->name[6 + slen + 1];
break;
}
}
if (!md) return 0;
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);
if (signature_alg == APK_SIGNATURE_MAX) {
return 0;
}
public_key = apk_trust_public_key_by_name(ctx->trust, name);
if (public_key != NULL) {
ctx->signature.public_key = public_key;
ctx->signature.type = signature_alg;
ctx->signature.data = apk_blob_from_istream(is, fi->size);
}
// TODO: check if its really a good idea to reset here
apk_verify_digest_start(&ctx->digest_ctx, signature_alg);
return 0;
}
/* apk_sign_ctx_mpart_cb() handles hashing archives and checking signatures, but
it can't do it alone. apk_sign_ctx_process_file() must be in the loop to
actually select which signature is to be verified and load the corresponding
@ -181,42 +201,43 @@ static int apk_sign_ctx_process_file(struct apk_sign_ctx *ctx, const struct apk_
static int apk_sign_ctx_mpart_cb(void *ctx, int part, apk_blob_t data)
{
struct apk_sign_ctx *sctx = (struct apk_sign_ctx *) ctx;
unsigned char calculated[EVP_MAX_MD_SIZE];
struct apk_digest digest;
int r, end_of_control;
if ((part == APK_MPART_DATA) ||
(part == APK_MPART_BOUNDARY && sctx->data_started))
if ((part == APK_MPART_DATA) || (part == APK_MPART_BOUNDARY && sctx->data_started)) {
goto update_digest;
}
/* Still in signature blocks? */
if (!sctx->control_started) {
if (part == APK_MPART_END)
if (part == APK_MPART_END) {
return -APKE_V2PKG_FORMAT;
}
goto reset_digest;
}
/* Grab state and mark all remaining block as data */
end_of_control = (sctx->data_started == 0);
end_of_control = (sctx->data_started == 0);
sctx->data_started = 1;
/* End of control-block and control does not have data checksum? */
if (sctx->has_data_checksum == 0 && end_of_control &&
part != APK_MPART_END)
if (sctx->has_data_checksum == 0 && end_of_control && part != APK_MPART_END)
goto update_digest;
/* Drool in the remainder of the digest block now, we will finish
* hashing it in all cases */
EVP_DigestUpdate(sctx->mdctx, data.ptr, data.len);
apk_digest_ctx_update(&sctx->digest_ctx, data.ptr, data.len);
if (sctx->has_data_checksum && !end_of_control) {
/* End of data-block with a checksum read from the control block */
EVP_DigestFinal_ex(sctx->mdctx, calculated, NULL);
if (EVP_MD_CTX_size(sctx->mdctx) == 0 ||
memcmp(calculated, sctx->data_checksum, EVP_MD_CTX_size(sctx->mdctx)) != 0)
apk_digest_ctx_final(&sctx->digest_ctx, &digest);
if (digest.len == 0 || memcmp(digest.data, sctx->data_checksum, digest.len) != 0) {
return -APKE_V2PKG_INTEGRITY;
}
sctx->data_verified = 1;
if (!sctx->allow_untrusted && !sctx->control_verified)
if (!sctx->allow_untrusted && !sctx->control_verified) {
return -APKE_SIGNATURE_UNTRUSTED;
}
return 0;
}
@ -230,51 +251,60 @@ static int apk_sign_ctx_mpart_cb(void *ctx, int part, apk_blob_t data)
switch (sctx->action) {
case APK_SIGN_VERIFY:
case APK_SIGN_VERIFY_AND_GENERATE:
if (sctx->signature.pkey != NULL) {
r = EVP_VerifyFinal(sctx->mdctx,
(unsigned char *) sctx->signature.data.ptr,
sctx->signature.data.len,
sctx->signature.pkey);
if (r != 1 && !sctx->allow_untrusted)
if (sctx->signature.public_key != NULL) {
r = apk_verify(sctx->signature.public_key,
&sctx->digest_ctx,
sctx->signature.data.ptr,
sctx->signature.data.len);
if (r != 0 && !sctx->allow_untrusted) {
return -APKE_SIGNATURE_INVALID;
}
} else {
r = 0;
if (!sctx->allow_untrusted)
if (!sctx->allow_untrusted) {
return -APKE_SIGNATURE_UNTRUSTED;
}
}
if (r == 1) {
sctx->control_verified = 1;
if (!sctx->has_data_checksum && part == APK_MPART_END)
if (!sctx->has_data_checksum && part == APK_MPART_END) {
sctx->data_verified = 1;
}
}
if (sctx->action == APK_SIGN_VERIFY_AND_GENERATE) {
goto generate_identity;
}
if (sctx->action == APK_SIGN_VERIFY_AND_GENERATE) goto generate_identity;
break;
case APK_SIGN_VERIFY_IDENTITY:
/* Reset digest for hashing data */
EVP_DigestFinal_ex(sctx->mdctx, calculated, NULL);
if (memcmp(calculated, sctx->identity.data,
sctx->identity.type) != 0)
apk_digest_ctx_final(&sctx->digest_ctx, &digest);
if (memcmp(digest.data, sctx->identity.data, sctx->identity.type) != 0) {
return -APKE_V2PKG_INTEGRITY;
}
sctx->control_verified = 1;
if (!sctx->has_data_checksum && part == APK_MPART_END)
if (!sctx->has_data_checksum && part == APK_MPART_END) {
sctx->data_verified = 1;
}
break;
case APK_SIGN_GENERATE:
generate_identity:
generate_identity:
/* Package identity is the checksum */
sctx->identity.type = EVP_MD_CTX_size(sctx->mdctx);
EVP_DigestFinal_ex(sctx->mdctx, sctx->identity.data, NULL);
if (!sctx->has_data_checksum) return -APKE_V2PKG_FORMAT;
sctx->identity.type = apk_digest_alg_len(sctx->digest_ctx.alg);
apk_digest_ctx_final(&sctx->digest_ctx, &digest);
memcpy(sctx->identity.data, digest.data, sctx->identity.type);
if (!sctx->has_data_checksum) {
return -APKE_V2PKG_FORMAT;
}
break;
}
reset_digest:
EVP_DigestInit_ex(sctx->mdctx, sctx->md, NULL);
EVP_MD_CTX_set_flags(sctx->mdctx, EVP_MD_CTX_FLAG_ONESHOT);
apk_digest_ctx_reset(&sctx->digest_ctx, sctx->digest_ctx.alg);
return 0;
update_digest:
EVP_MD_CTX_clear_flags(sctx->mdctx, EVP_MD_CTX_FLAG_ONESHOT);
EVP_DigestUpdate(sctx->mdctx, data.ptr, data.len);
apk_digest_ctx_update(&sctx->digest_ctx, data.ptr, data.len);
return 0;
}
@ -283,43 +313,56 @@ static int apk_extract_verify_v2index(struct apk_extract_ctx *ectx, apk_blob_t *
return 0;
}
static int apk_extract_verify_v2file(struct apk_extract_ctx *ectx, const struct apk_file_info *fi, struct apk_istream *is)
static int
apk_extract_verify_v2file(struct apk_extract_ctx *ectx, const struct apk_file_info *fi, struct apk_istream *is)
{
return 0;
}
static const struct apk_extract_ops extract_v2verify_ops = {
.v2index = apk_extract_verify_v2index,
.v2meta = apk_extract_v2_meta,
.file = apk_extract_verify_v2file,
.v2index = apk_extract_verify_v2index,
.v2meta = apk_extract_v2_meta,
.file = apk_extract_verify_v2file,
};
static int apk_extract_v2_entry(void *pctx, const struct apk_file_info *fi, struct apk_istream *is)
{
struct apk_extract_ctx *ectx = pctx;
struct apk_sign_ctx *sctx = ectx->pctx;
struct apk_sign_ctx *sctx = ectx->pctx;
int r, type;
r = apk_sign_ctx_process_file(sctx, fi, is);
if (r <= 0) return r;
if (r <= 0)
return r;
if (!sctx->control_started) return 0;
if (!sctx->control_started)
return 0;
if (!sctx->data_started || !sctx->has_data_checksum) {
if (fi->name[0] == '.') {
ectx->is_package = 1;
if (ectx->is_index) return -APKE_V2NDX_FORMAT;
if (!ectx->ops->v2meta) return -APKE_FORMAT_NOT_SUPPORTED;
if (ectx->is_index) {
return -APKE_V2NDX_FORMAT;
}
if (!ectx->ops->v2meta) {
return -APKE_FORMAT_NOT_SUPPORTED;
}
if (strcmp(fi->name, ".PKGINFO") == 0) {
return ectx->ops->v2meta(ectx, is);
} else if (strcmp(fi->name, ".INSTALL") == 0) {
return -APKE_V2PKG_FORMAT;
} else if ((type = apk_script_type(&fi->name[1])) != APK_SCRIPT_INVALID) {
if (ectx->ops->script) return ectx->ops->script(ectx, type, fi->size, is);
if (ectx->ops->script) {
return ectx->ops->script(ectx, type, fi->size, is);
}
}
} else {
ectx->is_index = 1;
if (ectx->is_package) return -APKE_V2PKG_FORMAT;
if (!ectx->ops->v2index) return -APKE_FORMAT_NOT_SUPPORTED;
if (ectx->is_package) {
return -APKE_V2PKG_FORMAT;
}
if (!ectx->ops->v2index) {
return -APKE_FORMAT_NOT_SUPPORTED;
}
if (strcmp(fi->name, "DESCRIPTION") == 0) {
free(ectx->desc.ptr);
ectx->desc = apk_blob_from_istream(is, fi->size);
@ -330,35 +373,47 @@ static int apk_extract_v2_entry(void *pctx, const struct apk_file_info *fi, stru
return 0;
}
if (!sctx->data_started) return 0;
if (!ectx->ops->file) return -ECANCELED;
if (!sctx->data_started)
return 0;
if (!ectx->ops->file)
return -ECANCELED;
return ectx->ops->file(ectx, fi, is);
}
int apk_extract_v2(struct apk_extract_ctx *ectx, struct apk_istream *is)
{
struct apk_ctx *ac = ectx->ac;
struct apk_ctx *ac = ectx->ac;
struct apk_trust *trust = apk_ctx_get_trust(ac);
struct apk_sign_ctx sctx;
int r, action;
if (ectx->generate_identity)
if (ectx->generate_identity) {
action = trust->allow_untrusted ? APK_SIGN_GENERATE : APK_SIGN_VERIFY_AND_GENERATE;
else if (ectx->identity)
} else if (ectx->identity) {
action = APK_SIGN_VERIFY_IDENTITY;
else
} else {
action = APK_SIGN_VERIFY;
}
if (!ectx->ops) {
ectx->ops = &extract_v2verify_ops;
}
if (!ectx->ops) ectx->ops = &extract_v2verify_ops;
ectx->pctx = &sctx;
apk_sign_ctx_init(&sctx, action, ectx->identity, trust);
r = apk_tar_parse(
apk_istream_gunzip_mpart(is, apk_sign_ctx_mpart_cb, &sctx),
apk_extract_v2_entry, ectx, apk_ctx_get_id_cache(ac));
if (r == -ECANCELED) r = 0;
if ((r == 0 || r == -APKE_EOF) && !ectx->is_package && !ectx->is_index)
r = apk_tar_parse(apk_istream_gunzip_mpart(is, apk_sign_ctx_mpart_cb, &sctx),
apk_extract_v2_entry,
ectx,
apk_ctx_get_id_cache(ac));
if (r == -ECANCELED) {
r = 0;
}
if ((r == 0 || r == -APKE_EOF) && !ectx->is_package && !ectx->is_index) {
r = ectx->ops->v2index ? -APKE_V2NDX_FORMAT : -APKE_V2PKG_FORMAT;
if (ectx->generate_identity) *ectx->identity = sctx.identity;
}
if (ectx->generate_identity) {
*ectx->identity = sctx.identity;
}
apk_sign_ctx_free(&sctx);
free(ectx->desc.ptr);
apk_extract_reset(ectx);
@ -370,14 +425,15 @@ void apk_extract_v2_control(struct apk_extract_ctx *ectx, apk_blob_t l, apk_blob
{
struct apk_sign_ctx *sctx = ectx->pctx;
if (!sctx || !sctx->control_started || sctx->data_started) return;
if (!sctx || !sctx->control_started || sctx->data_started) {
return;
}
// TODO check if reset is ok
if (apk_blob_compare(APK_BLOB_STR("datahash"), l) == 0) {
sctx->has_data_checksum = 1;
sctx->md = EVP_sha256();
apk_blob_pull_hexdump(
&r, APK_BLOB_PTR_LEN(sctx->data_checksum,
EVP_MD_size(sctx->md)));
apk_digest_ctx_reset(&sctx->digest_ctx, APK_DIGEST_SHA256);
apk_blob_pull_hexdump(&r, APK_BLOB_PTR_LEN(sctx->data_checksum, apk_digest_alg_len(APK_DIGEST_SHA256)));
}
}
@ -385,11 +441,13 @@ int apk_extract_v2_meta(struct apk_extract_ctx *ectx, struct apk_istream *is)
{
apk_blob_t k, v, token = APK_BLOB_STRLIT("\n");
while (apk_istream_get_delim(is, token, &k) == 0) {
if (k.len < 1 || k.ptr[0] == '#') continue;
if (k.len < 1 || k.ptr[0] == '#') {
continue;
}
if (apk_blob_split(k, APK_BLOB_STRLIT(" = "), &k, &v)) {
apk_extract_v2_control(ectx, k, v);
}
}
return 0;
}

View File

@ -14,7 +14,8 @@ libapk_src = [
'context.c',
'crypto_core.c',
'crypto_digest.c',
'crypto_openssl.c',
'crypto_public.c',
'crypto_secret.c',
'database.c',
'extract_v2.c',
'extract_v3.c',
@ -44,7 +45,6 @@ libapk_headers = [
'apk_fs.h',
'apk_hash.h',
'apk_io.h',
'apk_openssl.h',
'apk_package.h',
'apk_pathbuilder.h',
'apk_print.h',

View File

@ -19,9 +19,6 @@
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include "apk_openssl.h"
#include <openssl/pem.h>
#include "apk_defines.h"
#include "apk_package.h"
#include "apk_database.h"
@ -440,7 +437,7 @@ int apk_deps_write_layer(struct apk_database *db, struct apk_dependency_array *d
apk_blob_push_dep(&blob, db, &deps->item[i]);
blob = apk_blob_pushed(APK_BLOB_BUF(tmp), blob);
if (APK_BLOB_IS_NULL(blob) ||
if (APK_BLOB_IS_NULL(blob) ||
apk_ostream_write(os, blob.ptr, blob.len) < 0)
return -1;

View File

@ -2,7 +2,7 @@
#include "apk_trust.h"
#include "apk_io.h"
static struct apk_trust_key *apk_trust_load_key(int dirfd, const char *filename)
static struct apk_trust_key *apk_trust_load_public(int dirfd, const char *filename)
{
struct apk_trust_key *key;
int r;
@ -10,7 +10,7 @@ static struct apk_trust_key *apk_trust_load_key(int dirfd, const char *filename)
key = calloc(1, sizeof *key);
if (!key) return ERR_PTR(-ENOMEM);
r = apk_pkey_load(&key->key, dirfd, filename);
r = apk_public_key_load(&key->key, dirfd, filename);
if (r) {
free(key);
return ERR_PTR(r);
@ -24,7 +24,7 @@ static struct apk_trust_key *apk_trust_load_key(int dirfd, const char *filename)
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);
struct apk_trust_key *key = apk_trust_load_public(dirfd, filename);
if (!IS_ERR(key))
list_add_tail(&key->key_node, &trust->trusted_key_list);
@ -56,7 +56,7 @@ static void __apk_trust_free_keys(struct list_head *h)
list_for_each_entry_safe(tkey, n, h, key_node) {
list_del(&tkey->key_node);
apk_pkey_free(&tkey->key);
apk_public_key_free(&tkey->key);
free(tkey->filename);
free(tkey);
}
@ -69,7 +69,7 @@ void apk_trust_free(struct apk_trust *trust)
apk_digest_ctx_free(&trust->dctx);
}
struct apk_pkey *apk_trust_key_by_name(struct apk_trust *trust, const char *filename)
struct apk_public_key *apk_trust_public_key_by_name(struct apk_trust *trust, const char *filename)
{
struct apk_trust_key *tkey;
@ -97,7 +97,7 @@ static int option_parse_signing(void *ctx, struct apk_ctx *ac, int optch, const
switch (optch) {
case OPT_SIGN_sign_key:
key = apk_trust_load_key(AT_FDCWD, optarg);
key = apk_trust_load_public(AT_FDCWD, optarg);
if (IS_ERR(key)) {
apk_err(out, "Failed to load signing key: %s: %s",
optarg, apk_error_str(PTR_ERR(key)));