diff --git a/meson.build b/meson.build index 5c7f2db..b37f3b9 100644 --- a/meson.build +++ b/meson.build @@ -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') diff --git a/src/Makefile b/src/Makefile index a85cbdd..7411e79 100644 --- a/src/Makefile +++ b/src/Makefile @@ -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) diff --git a/src/adb.c b/src/adb.c index 93ae8af..e89dc3f 100644 --- a/src/adb.c +++ b/src/adb.c @@ -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; } diff --git a/src/apk_crypto.h b/src/apk_crypto.h index 219817c..f5827b9 100644 --- a/src/apk_crypto.h +++ b/src/apk_crypto.h @@ -9,20 +9,16 @@ #ifndef APK_CRYPTO_H #define APK_CRYPTO_H -#include -#include #include #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 diff --git a/src/apk_trust.h b/src/apk_trust.h index 6e6f6b8..409ab0b 100644 --- a/src/apk_trust.h +++ b/src/apk_trust.h @@ -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 diff --git a/src/crypto_digest.c b/src/crypto_digest.c index ff26de2..8f40dc8 100644 --- a/src/crypto_digest.c +++ b/src/crypto_digest.c @@ -1,24 +1,14 @@ +#include #include #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; diff --git a/src/crypto_openssl.c b/src/crypto_openssl.c deleted file mode 100644 index b0915cf..0000000 --- a/src/crypto_openssl.c +++ /dev/null @@ -1,133 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#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; -} diff --git a/src/crypto_public.c b/src/crypto_public.c new file mode 100644 index 0000000..d4ff29a --- /dev/null +++ b/src/crypto_public.c @@ -0,0 +1,350 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 diff --git a/src/crypto_secret.c b/src/crypto_secret.c new file mode 100644 index 0000000..9dcd0f4 --- /dev/null +++ b/src/crypto_secret.c @@ -0,0 +1,347 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 diff --git a/src/crypto_sign.c b/src/crypto_sign.c deleted file mode 100644 index 1041cf0..0000000 --- a/src/crypto_sign.c +++ /dev/null @@ -1,232 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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; -} diff --git a/src/database.c b/src/database.c index 928a864..2516e62 100644 --- a/src/database.c +++ b/src/database.c @@ -7,19 +7,20 @@ * SPDX-License-Identifier: GPL-2.0-only */ +#include #include -#include #include +#include #include #include -#include -#include -#include #include -#include +#include +#include +#include #include -#include #include +#include +#include #ifdef __linux__ # include diff --git a/src/extract_v2.c b/src/extract_v2.c index f75c553..419f817 100644 --- a/src/extract_v2.c +++ b/src/extract_v2.c @@ -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; } - diff --git a/src/meson.build b/src/meson.build index 24ed5fd..f470d56 100644 --- a/src/meson.build +++ b/src/meson.build @@ -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', diff --git a/src/package.c b/src/package.c index b160176..8791b43 100644 --- a/src/package.c +++ b/src/package.c @@ -19,9 +19,6 @@ #include #include -#include "apk_openssl.h" -#include - #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; diff --git a/src/trust.c b/src/trust.c index c65377d..7934497 100644 --- a/src/trust.c +++ b/src/trust.c @@ -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)));