#include <openssl/rand.h>
#include <pakfire/constants.h>
+#include <pakfire/ctx.h>
#include <pakfire/i18n.h>
#include <pakfire/key.h>
#include <pakfire/logging.h>
#define ERROR_MAX 1024
struct pakfire_key {
- struct pakfire* pakfire;
+ struct pakfire_ctx* ctx;
int nrefs;
// Algorithm
return !memcmp(*id1, *id2, sizeof(*id1));
}
-static int pakfire_key_create(struct pakfire_key** key, struct pakfire* pakfire,
+static int pakfire_key_create(struct pakfire_key** key, struct pakfire_ctx* ctx,
const pakfire_key_algo_t algo, const pakfire_key_id id, EVP_PKEY* pkey, const char* comment) {
int r;
if (!k)
return 1;
- // Initialize pakfire and reference counter
- k->pakfire = pakfire_ref(pakfire);
+ // Store a reference to the context
+ k->ctx = pakfire_ctx_ref(ctx);
+
+ // Initialize the reference counter
k->nrefs = 1;
// Store the algorithm
break;
default:
- ERROR(pakfire, "Unsupported key algorithm %u\n", algo);
+ CTX_ERROR(k->ctx, "Unsupported key algorithm %u\n", algo);
errno = ENOTSUP;
goto ERROR;
}
// Free the key
if (key->pkey)
EVP_PKEY_free(key->pkey);
-
- pakfire_unref(key->pakfire);
+ if (key->ctx)
+ pakfire_ctx_unref(key->ctx);
free(key);
}
return key->comment;
}
-PAKFIRE_EXPORT int pakfire_key_generate(struct pakfire_key** key, struct pakfire* pakfire,
+PAKFIRE_EXPORT int pakfire_key_generate(struct pakfire_key** key, struct pakfire_ctx* ctx,
const pakfire_key_algo_t algo, const char* comment) {
EVP_PKEY* pkey = NULL;
EVP_PKEY_CTX* pctx = NULL;
break;
default:
- ERROR(pakfire, "Invalid key algorithm %u\n", algo);
+ CTX_ERROR(ctx, "Invalid key algorithm %u\n", algo);
errno = EINVAL;
return 1;
}
// Generate a random key ID
r = RAND_bytes((unsigned char*)&key_id, sizeof(key_id));
if (r < 0) {
- ERROR(pakfire, "Could not generate the key ID\n");
+ CTX_ERROR(ctx, "Could not generate the key ID\n");
r = 1;
goto ERROR;
}
// Setup the context
pctx = EVP_PKEY_CTX_new_id(id, NULL);
if (!pctx) {
- ERROR(pakfire, "Could not allocate the OpenSSL context: %m\n");
+ CTX_ERROR(ctx, "Could not allocate the OpenSSL context: %m\n");
r = 1;
goto ERROR;
}
if (r < 1) {
ERR_error_string_n(r, error, sizeof(error));
- ERROR(pakfire, "Could not prepare the context: %s\n", error);
+ CTX_ERROR(ctx, "Could not prepare the context: %s\n", error);
r = 1;
goto ERROR;
}
if (r < 1) {
ERR_error_string_n(r, error, sizeof(error));
- ERROR(pakfire, "Could not generate the key: %s\n", error);
+ CTX_ERROR(ctx, "Could not generate the key: %s\n", error);
r = 1;
goto ERROR;
}
// Create a key object
- r = pakfire_key_create(key, pakfire, algo, key_id, pkey, comment);
+ r = pakfire_key_create(key, ctx, algo, key_id, pkey, comment);
if (r)
goto ERROR;
*/
static int pakfire_key_import_secret_key(struct pakfire_key** key,
- struct pakfire* pakfire, const char* comment,
+ struct pakfire_ctx* ctx, const char* comment,
const struct pakfire_key_private_key* buffer) {
const pakfire_key_algo_t algo = PAKFIRE_KEY_ALGO_ED25519;
EVP_PKEY* pkey = NULL;
// Check the signature algorithm
if (buffer->sig_algo[0] != 'E' || buffer->sig_algo[1] != 'd') {
- ERROR(pakfire, "Unsupported signature algorithm\n");
+ CTX_ERROR(ctx, "Unsupported signature algorithm\n");
errno = ENOTSUP;
r = 1;
goto ERROR;
// Check the KDF algorithm
if (buffer->kdf_algo[0] != 'B' || buffer->kdf_algo[1] != 'K') {
- ERROR(pakfire, "Unsupported KDF algorithm\n");
+ CTX_ERROR(ctx, "Unsupported KDF algorithm\n");
errno = ENOTSUP;
r = 1;
goto ERROR;
// We don't support encrypted keys here
if (buffer->kdf_rounds) {
- ERROR(pakfire, "Encrypted keys are not supported\n");
+ CTX_ERROR(ctx, "Encrypted keys are not supported\n");
errno = ENOTSUP;
r = 1;
goto ERROR;
// Compute a SHA512 checksum over the key material
r = EVP_Digest(&buffer->keys, sizeof(buffer->keys), checksum, &length, EVP_sha512(), NULL);
if (r < 0) {
- ERROR(pakfire, "Could not compute the checksum: %m\n");
+ CTX_ERROR(ctx, "Could not compute the checksum: %m\n");
r = 1;
goto ERROR;
}
// Compare the checksum
if (memcmp(buffer->checksum, checksum, sizeof(buffer->checksum)) != 0) {
- ERROR(pakfire, "Checksum mismatch\n");
+ CTX_ERROR(ctx, "Checksum mismatch\n");
r = 1;
goto ERROR;
}
if (!pkey) {
ERR_error_string_n(ERR_get_error(), error, sizeof(error));
- ERROR(pakfire, "Could not load secret key: %s\n", error);
+ CTX_ERROR(ctx, "Could not load secret key: %s\n", error);
r = 1;
goto ERROR;
}
// Create a new key object
- r = pakfire_key_create(key, pakfire, algo, buffer->id, pkey, comment);
+ r = pakfire_key_create(key, ctx, algo, buffer->id, pkey, comment);
if (r)
goto ERROR;
}
static int pakfire_key_import_public_key(struct pakfire_key** key,
- struct pakfire* pakfire, const char* comment,
+ struct pakfire_ctx* ctx, const char* comment,
const struct pakfire_key_public_key* buffer) {
const pakfire_key_algo_t algo = PAKFIRE_KEY_ALGO_ED25519;
EVP_PKEY* pkey = NULL;
// Check the signature algorithm
if (buffer->sig_algo[0] != 'E' || buffer->sig_algo[1] != 'd') {
- ERROR(pakfire, "Unsupported signature algorithm\n");
+ CTX_ERROR(ctx, "Unsupported signature algorithm\n");
errno = ENOTSUP;
r = 1;
goto ERROR;
if (!pkey) {
ERR_error_string_n(ERR_get_error(), error, sizeof(error));
- ERROR(pakfire, "Could not load public key: %s\n", error);
+ CTX_ERROR(ctx, "Could not load public key: %s\n", error);
r = 1;
goto ERROR;
}
// Create a new key object
- r = pakfire_key_create(key, pakfire, algo, buffer->id, pkey, comment);
+ r = pakfire_key_create(key, ctx, algo, buffer->id, pkey, comment);
if (r)
goto ERROR;
}
PAKFIRE_EXPORT int pakfire_key_import(struct pakfire_key** key,
- struct pakfire* pakfire, FILE* f) {
+ struct pakfire_ctx* ctx, FILE* f) {
void* buffer = NULL;
size_t buffer_length = 0;
int r;
// The first line must start with "untrusted comment:"
case 1:
if (!pakfire_string_startswith(line, "untrusted comment: ")) {
- ERROR(pakfire, "The first line must start with 'untrusted comment: '"
+ CTX_ERROR(ctx, "The first line must start with 'untrusted comment: '"
" and not %s\n", line);
errno = EINVAL;
r = 1;
// Copy the comment
r = pakfire_string_set(comment, line + strlen("untrusted comment: "));
if (r) {
- ERROR(pakfire, "Could not copy comment: %m\n");
+ CTX_ERROR(ctx, "Could not copy comment: %m\n");
r = 1;
goto ERROR;
}
// The second line should hold the key
case 2:
// Decode the key
- r = pakfire_b64decode(pakfire, &buffer, &buffer_length, line);
+ r = pakfire_b64decode(ctx, &buffer, &buffer_length, line);
if (r) {
- ERROR(pakfire, "Could not decode the key: %m\n");
+ CTX_ERROR(ctx, "Could not decode the key: %m\n");
errno = EINVAL;
r = 1;
goto ERROR;
switch (buffer_length) {
// Public Key
case sizeof(struct pakfire_key_public_key):
- r = pakfire_key_import_public_key(key, pakfire, comment,
+ r = pakfire_key_import_public_key(key, ctx, comment,
(struct pakfire_key_public_key*)buffer);
break;
// Private Key
case sizeof(struct pakfire_key_private_key):
- r = pakfire_key_import_secret_key(key, pakfire, comment,
+ r = pakfire_key_import_secret_key(key, ctx, comment,
(struct pakfire_key_private_key*)buffer);
break;
// Unknown key
default:
- ERROR(pakfire, "Unsupported key type\n");
+ CTX_ERROR(ctx, "Unsupported key type\n");
errno = ENOTSUP;
r = 1;
goto ERROR;
}
int pakfire_key_import_from_string(struct pakfire_key** key,
- struct pakfire* pakfire, const char* data, const size_t length) {
+ struct pakfire_ctx* ctx, const char* data, const size_t length) {
FILE* f = NULL;
int r;
// Map the data to a file
f = fmemopen((char*)data, length, "r");
if (!f) {
- ERROR(pakfire, "Could not map the key to file: %m\n");
+ CTX_ERROR(ctx, "Could not map the key to file: %m\n");
r = 1;
goto ERROR;
}
// Import the key
- r = pakfire_key_import(key, pakfire, f);
+ r = pakfire_key_import(key, ctx, f);
ERROR:
if (f)
if (r < 0) {
ERR_error_string_n(ERR_get_error(), error, sizeof(error));
- ERROR(key->pakfire, "Could not extract the public key: %s\n", error);
+ CTX_ERROR(key->ctx, "Could not extract the public key: %s\n", error);
return 1;
}
if (l > length) {
- ERROR(key->pakfire, "The buffer was too small to write the public key\n");
+ CTX_ERROR(key->ctx, "The buffer was too small to write the public key\n");
errno = ENOBUFS;
return 1;
}
if (r < 0) {
ERR_error_string_n(ERR_get_error(), error, sizeof(error));
- ERROR(key->pakfire, "Could not extract the secret key: %s\n", error);
+ CTX_ERROR(key->ctx, "Could not extract the secret key: %s\n", error);
return 1;
}
if (l > length) {
- ERROR(key->pakfire, "The buffer was too small to write the secret key\n");
+ CTX_ERROR(key->ctx, "The buffer was too small to write the secret key\n");
errno = ENOBUFS;
return 1;
}
break;
default:
- ERROR(key->pakfire, "Unknown algorithm\n");
+ CTX_ERROR(key->ctx, "Unknown algorithm\n");
return 1;
}
// Generate a salt
r = RAND_bytes(buffer->kdf_salt, sizeof(buffer->kdf_salt));
if (r < 1) {
- ERROR(key->pakfire, "Could not generate salt\n");
+ CTX_ERROR(key->ctx, "Could not generate salt\n");
return 1;
}
// Write the public key
r = pakfire_key_get_public_key(key, buffer->keys.public, sizeof(buffer->keys.public));
if (r) {
- ERROR(key->pakfire, "Could not export the public key: %m\n");
+ CTX_ERROR(key->ctx, "Could not export the public key: %m\n");
return r;
}
// Write the secret key
r = pakfire_key_get_secret_key(key, buffer->keys.secret, sizeof(buffer->keys.secret));
if (r) {
- ERROR(key->pakfire, "Could not export the secret key: %m\n");
+ CTX_ERROR(key->ctx, "Could not export the secret key: %m\n");
return r;
}
// Compute a SHA512 checksum over the key material
r = EVP_Digest(&buffer->keys, sizeof(buffer->keys), checksum, &length, EVP_sha512(), NULL);
if (r < 0) {
- ERROR(key->pakfire, "Could not compute the checksum: %m\n");
+ CTX_ERROR(key->ctx, "Could not compute the checksum: %m\n");
return 1;
}
break;
default:
- ERROR(key->pakfire, "Unknown algorithm\n");
+ CTX_ERROR(key->ctx, "Unknown algorithm\n");
return 1;
}
// Write the public key
r = pakfire_key_get_public_key(key, buffer->pubkey, sizeof(buffer->pubkey));
if (r) {
- ERROR(key->pakfire, "Could not export the public key: %m\n");
+ CTX_ERROR(key->ctx, "Could not export the public key: %m\n");
return r;
}
if (*key->comment) {
r = fprintf(f, "untrusted comment: %s\n", key->comment);
if (r < 0) {
- ERROR(key->pakfire, "Could not write comment: %m\n");
+ CTX_ERROR(key->ctx, "Could not write comment: %m\n");
r = 1;
goto ERROR;
}
// Setup the base64 encoder
b64 = BIO_new(BIO_f_base64());
if (!b64) {
- ERROR(key->pakfire, "Could not setup the base64 encoder\n");
+ CTX_ERROR(key->ctx, "Could not setup the base64 encoder\n");
r = 1;
goto ERROR;
}
bio = BIO_new_fp(f, BIO_NOCLOSE);
if (!bio) {
- ERROR(key->pakfire, "Could not open BIO\n");
+ CTX_ERROR(key->ctx, "Could not open BIO\n");
r = 1;
goto ERROR;
}
// Write the output
r = BIO_write(b64, &public_key, sizeof(public_key));
if (r < 0) {
- ERROR(key->pakfire, "Could not write the public key\n");
+ CTX_ERROR(key->ctx, "Could not write the public key\n");
r = 1;
goto ERROR;
}
// Write the output
r = BIO_write(b64, &private_key, sizeof(private_key));
if (r < 0) {
- ERROR(key->pakfire, "Could not write the private key\n");
+ CTX_ERROR(key->ctx, "Could not write the private key\n");
r = 1;
goto ERROR;
}
// Allocate a buffer in memory
fd = memfd_create("pakfire-key-dump", MFD_CLOEXEC);
if (fd < 0) {
- ERROR(key->pakfire, "Could not allocate a temporary file: %m\n");
+ CTX_ERROR(key->ctx, "Could not allocate a temporary file: %m\n");
r = 1;
goto ERROR;
}
// Re-open as FILE handle
f = fdopen(fd, "r+");
if (!f) {
- ERROR(key->pakfire, "Could not open file handle for temporary file: %m\n");
+ CTX_ERROR(key->ctx, "Could not open file handle for temporary file: %m\n");
r = 1;
goto ERROR;
}
// Export the public part of the key
r = pakfire_key_export(key, f, PAKFIRE_KEY_EXPORT_MODE_PUBLIC);
if (r) {
- ERROR(key->pakfire, "Could not export key: %m\n");
+ CTX_ERROR(key->ctx, "Could not export key: %m\n");
goto ERROR;
}
// Allocate a buffer
buffer = calloc(1, length + 1);
if (!buffer) {
- ERROR(key->pakfire, "Could not allocate buffer of %zu byte(s)\n", length + 1);
+ CTX_ERROR(key->ctx, "Could not allocate buffer of %zu byte(s)\n", length + 1);
r = 1;
goto ERROR;
}
// Read everything into the buffer
size_t bytes_read = fread(buffer, 1, length, f);
if (bytes_read < length) {
- ERROR(key->pakfire, "Could not read back the buffer: %m\n");
+ CTX_ERROR(key->ctx, "Could not read back the buffer: %m\n");
r = 1;
goto ERROR;
}
// Create a message digest context
mdctx = EVP_MD_CTX_new();
if (!mdctx) {
- ERROR(key->pakfire, "Could not initialize the message digest context: %m\n");
+ CTX_ERROR(key->ctx, "Could not initialize the message digest context: %m\n");
r = 1;
goto ERROR;
}
// Setup the context
r = EVP_DigestSignInit(mdctx, NULL, NULL, NULL, key->pkey);
if (r < 1) {
- ERROR(key->pakfire, "Could not setup context\n");
+ CTX_ERROR(key->ctx, "Could not setup context\n");
r = 1;
goto ERROR;
}
if (r < 1) {
ERR_error_string_n(ERR_get_error(), error, sizeof(error));
- ERROR(key->pakfire, "Could not sign content: %s\n", error);
+ CTX_ERROR(key->ctx, "Could not sign content: %s\n", error);
r = 1;
goto ERROR;
}
if (comment) {
r = fprintf(f, "untrusted comment: %s\n", comment);
if (r < 0) {
- ERROR(key->pakfire, "Could not write comment: %m\n");
+ CTX_ERROR(key->ctx, "Could not write comment: %m\n");
r = 1;
goto ERROR;
}
}
// Encode the signature to base64
- r = pakfire_b64encode(key->pakfire, &s, &signature, sizeof(signature));
+ r = pakfire_b64encode(key->ctx, &s, &signature, sizeof(signature));
if (r)
goto ERROR;
// Write the signature
r = fprintf(f, "%s\n", s);
if (r < 0) {
- ERROR(key->pakfire, "Could not write the signature: %m\n");
+ CTX_ERROR(key->ctx, "Could not write the signature: %m\n");
r = 1;
goto ERROR;
}
// The first line must start with "untrusted comment:"
case 1:
if (!pakfire_string_startswith(line, "untrusted comment:")) {
- ERROR(key->pakfire, "The first line must start with 'untrusted comment:'\n");
+ CTX_ERROR(key->ctx, "The first line must start with 'untrusted comment:'\n");
errno = EINVAL;
r = 1;
goto ERROR;
// The second line should hold the signature
case 2:
// Decode the key
- r = pakfire_b64decode(key->pakfire, &buffer, &buffer_length, line);
+ r = pakfire_b64decode(key->ctx, &buffer, &buffer_length, line);
if (r) {
- ERROR(key->pakfire, "Could not decode the signature: %m\n");
+ CTX_ERROR(key->ctx, "Could not decode the signature: %m\n");
errno = EINVAL;
r = 1;
goto ERROR;
// Check if we support the signature type
if (signature->sig_algo[0] != 'E' || signature->sig_algo[1] != 'd') {
- ERROR(key->pakfire, "Unknown signature type\n");
+ CTX_ERROR(key->ctx, "Unknown signature type\n");
errno = ENOTSUP;
r = 1;
goto ERROR;
break;
default:
- ERROR(key->pakfire, "Unknown signature type\n");
+ CTX_ERROR(key->ctx, "Unknown signature type\n");
errno = ENOTSUP;
r = 1;
goto ERROR;
EVP_MD_CTX* mdctx = NULL;
int r;
- DEBUG(key->pakfire, "Verifying signature...\n");
+ CTX_DEBUG(key->ctx, "Verifying signature...\n");
// Check the key ID
if (!pakfire_key_id_equals(&key->id, &signature->key_id)) {
- ERROR(key->pakfire, "The signature has been created with a different key\n");
+ CTX_ERROR(key->ctx, "The signature has been created with a different key\n");
errno = EBADMSG;
r = 1;
goto ERROR;
// Create message digest context
mdctx = EVP_MD_CTX_new();
if (!mdctx) {
- ERROR(key->pakfire, "Could not create the message digest context\n");
+ CTX_ERROR(key->ctx, "Could not create the message digest context\n");
r = 1;
goto ERROR;
}
// Setup the context for verification
r = EVP_DigestVerifyInit(mdctx, NULL, NULL, NULL, key->pkey);
if (r < 1) {
- ERROR(key->pakfire, "Could not setup the verification context\n");
+ CTX_ERROR(key->ctx, "Could not setup the verification context\n");
r = 1;
goto ERROR;
}
switch (r) {
// Fail
case 0:
- ERROR(key->pakfire, "Signature verification failed\n");
+ CTX_ERROR(key->ctx, "Signature verification failed\n");
errno = EBADMSG;
r = 1;
break;
// Success
case 1:
- DEBUG(key->pakfire, "Signature verification successful\n");
+ CTX_DEBUG(key->ctx, "Signature verification successful\n");
r = 0;
break;
// Error
default:
- ERROR(key->pakfire, "Could not perform signature verification\n");
+ CTX_ERROR(key->ctx, "Could not perform signature verification\n");
r = 1;
goto ERROR;
}
// Read the signature
r = pakfire_key_read_signature(key, &signature, f);
if (r) {
- ERROR(key->pakfire, "Could not read signature: %m\n");
+ CTX_ERROR(key->ctx, "Could not read signature: %m\n");
return r;
}
// Verify signature
r = pakfire_key_verify_signature(key, &signature, data, length);
if (r) {
- ERROR(key->pakfire, "Could not verify signature: %m\n");
+ CTX_ERROR(key->ctx, "Could not verify signature: %m\n");
return r;
}