From 742cb7f6606d01f26b0d56a759c799d576cd6d21 Mon Sep 17 00:00:00 2001 From: Landon Fuller Date: Mon, 16 Jan 2006 02:01:47 +0000 Subject: [PATCH 1/1] - Add support for testing the availability of a PEM-encoded private key - Load private keys from Master Keys and Signing Keys where possible - Clarify pki_* variable names in the JCR structure. - Fix small bugs in RES_CLIENT deallocation and copying. - Add full support for decoding and decrypting crypto session w/ symmetric keys git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@2749 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/src/filed/backup.c | 2 +- bacula/src/filed/filed.c | 81 ++++++++++++------- bacula/src/filed/filed_conf.c | 37 +++++---- bacula/src/filed/filed_conf.h | 8 +- bacula/src/filed/job.c | 2 +- bacula/src/filed/restore.c | 34 +++++++- bacula/src/jcr.h | 2 +- bacula/src/lib/crypto.c | 147 +++++++++++++++++++++++++++++++--- bacula/src/lib/crypto.h | 9 ++- bacula/src/lib/protos.h | 2 + 10 files changed, 256 insertions(+), 68 deletions(-) diff --git a/bacula/src/filed/backup.c b/bacula/src/filed/backup.c index 34fed539da..6812d8cf74 100644 --- a/bacula/src/filed/backup.c +++ b/bacula/src/filed/backup.c @@ -88,7 +88,7 @@ bool blast_data_to_storage_daemon(JCR *jcr, char *addr) size_t size = 0; /* Create per-job session encryption context */ - jcr->pki_session = crypto_session_new(cipher, jcr->pki_readers); + jcr->pki_session = crypto_session_new(cipher, jcr->pki_recipients); /* Get the session data size */ if (crypto_session_encode(jcr->pki_session, NULL, &size) == false) { diff --git a/bacula/src/filed/filed.c b/bacula/src/filed/filed.c index c97926d0c7..f274444fe6 100644 --- a/bacula/src/filed/filed.c +++ b/bacula/src/filed/filed.c @@ -341,7 +341,7 @@ static int check_resources() me->pki_sign = true; } - if ((me->pki_encrypt || me->pki_sign) && !me->pki_keypairfile) { + if ((me->pki_encrypt || me->pki_sign) && !me->pki_keypair_file) { Emsg2(M_FATAL, 0, _("\"PKI Key Pair\" must be defined for File" " daemon \"%s\" in %s if either \"PKI Sign\" or" " \"PKI Encrypt\" are enabled.\n"), me->hdr.name, configfile); @@ -351,20 +351,19 @@ static int check_resources() /* If everything is well, attempt to initialize our public/private keys */ if (OK && (me->pki_encrypt || me->pki_sign)) { char *filepath; - /* Load our keypair */ me->pki_keypair = crypto_keypair_new(); if (!me->pki_keypair) { Emsg0(M_FATAL, 0, _("Failed to allocate a new keypair object.\n")); OK = false; } else { - if (!crypto_keypair_load_cert(me->pki_keypair, me->pki_keypairfile)) { + if (!crypto_keypair_load_cert(me->pki_keypair, me->pki_keypair_file)) { Emsg2(M_FATAL, 0, _("Failed to load public certificate for File" " daemon \"%s\" in %s.\n"), me->hdr.name, configfile); OK = false; } - if (!crypto_keypair_load_key(me->pki_keypair, me->pki_keypairfile, NULL, NULL)) { + if (!crypto_keypair_load_key(me->pki_keypair, me->pki_keypair_file, NULL, NULL)) { Emsg2(M_FATAL, 0, _("Failed to load private key for File" " daemon \"%s\" in %s.\n"), me->hdr.name, configfile); OK = false; @@ -375,11 +374,13 @@ static int check_resources() * Trusted Signers. We're always trusted. */ me->pki_signers = New(alist(10, not_owned_by_alist)); - me->pki_signers->append(crypto_keypair_dup(me->pki_keypair)); + if (me->pki_keypair) { + me->pki_signers->append(crypto_keypair_dup(me->pki_keypair)); + } - /* If additional trusted keys have been specified, load them up */ - if (me->pki_trustedkeys) { - foreach_alist(filepath, me->pki_trustedkeys) { + /* If additional signing public keys have been specified, load them up */ + if (me->pki_signing_key_files) { + foreach_alist(filepath, me->pki_signing_key_files) { X509_KEYPAIR *keypair; keypair = crypto_keypair_new(); @@ -389,6 +390,16 @@ static int check_resources() } else { if (crypto_keypair_load_cert(keypair, filepath)) { me->pki_signers->append(keypair); + + /* Attempt to load a private key, if available */ + if (crypto_keypair_has_key(filepath)) { + if (!crypto_keypair_load_key(keypair, filepath, NULL, NULL)) { + Emsg3(M_FATAL, 0, _("Failed to load private key from file %s for File" + " daemon \"%s\" in %s.\n"), filepath, me->hdr.name, configfile); + OK = false; + } + } + } else { Emsg3(M_FATAL, 0, _("Failed to load trusted signer certificate" " from file %s for File daemon \"%s\" in %s.\n"), filepath, me->hdr.name, configfile); @@ -398,32 +409,42 @@ static int check_resources() } } - if (me->pki_encrypt) { - /* - * Trusted readers. We're always trusted. - * The symmetric session key will be encrypted for each of these readers. - */ - me->pki_readers = New(alist(10, not_owned_by_alist)); - me->pki_readers->append(crypto_keypair_dup(me->pki_keypair)); + /* + * Crypto recipients. We're always included as a recipient. + * The symmetric session key will be encrypted for each of these readers. + */ + me->pki_recipients = New(alist(10, not_owned_by_alist)); + if (me->pki_keypair) { + me->pki_recipients->append(crypto_keypair_dup(me->pki_keypair)); + } - /* If additional keys have been specified, load them up */ - if (me->pki_masterkeys) { - foreach_alist(filepath, me->pki_masterkeys) { - X509_KEYPAIR *keypair; + /* If additional keys have been specified, load them up */ + if (me->pki_master_key_files) { + foreach_alist(filepath, me->pki_master_key_files) { + X509_KEYPAIR *keypair; - keypair = crypto_keypair_new(); - if (!keypair) { - Emsg0(M_FATAL, 0, _("Failed to allocate a new keypair object.\n")); - OK = false; - } else { - if (crypto_keypair_load_cert(keypair, filepath)) { - me->pki_signers->append(keypair); - } else { - Emsg3(M_FATAL, 0, _("Failed to load master key certificate" - " from file %s for File daemon \"%s\" in %s.\n"), filepath, me->hdr.name, configfile); - OK = false; + keypair = crypto_keypair_new(); + if (!keypair) { + Emsg0(M_FATAL, 0, _("Failed to allocate a new keypair object.\n")); + OK = false; + } else { + if (crypto_keypair_load_cert(keypair, filepath)) { + me->pki_recipients->append(keypair); + + /* Attempt to load a private key, if available */ + if (crypto_keypair_has_key(filepath)) { + if (!crypto_keypair_load_key(keypair, filepath, NULL, NULL)) { + Emsg3(M_FATAL, 0, _("Failed to load private key from file %s for File" + " daemon \"%s\" in %s.\n"), filepath, me->hdr.name, configfile); + OK = false; + } } + + } else { + Emsg3(M_FATAL, 0, _("Failed to load master key certificate" + " from file %s for File daemon \"%s\" in %s.\n"), filepath, me->hdr.name, configfile); + OK = false; } } } diff --git a/bacula/src/filed/filed_conf.c b/bacula/src/filed/filed_conf.c index 442e6dd63c..515b7944d2 100644 --- a/bacula/src/filed/filed_conf.c +++ b/bacula/src/filed/filed_conf.c @@ -91,9 +91,9 @@ static RES_ITEM cli_items[] = { {"maximumnetworkbuffersize", store_pint, ITEM(res_client.max_network_buffer_size), 0, 0, 0}, {"pkisignatures", store_yesno, ITEM(res_client.pki_sign), 1, ITEM_DEFAULT, 0}, {"pkiencryption", store_yesno, ITEM(res_client.pki_encrypt), 1, ITEM_DEFAULT, 0}, - {"pkikeypair", store_dir, ITEM(res_client.pki_keypairfile), 0, 0, 0}, - {"pkitrustedsigner", store_alist_str, ITEM(res_client.pki_trustedkeys), 0, 0, 0}, - {"pkimasterkey", store_alist_str, ITEM(res_client.pki_masterkeys), 0, 0, 0}, + {"pkikeypair", store_dir, ITEM(res_client.pki_keypair_file), 0, 0, 0}, + {"pkisigner", store_alist_str, ITEM(res_client.pki_signing_key_files), 0, 0, 0}, + {"pkimasterkey", store_alist_str, ITEM(res_client.pki_master_key_files), 0, 0, 0}, {"tlsenable", store_yesno, ITEM(res_client.tls_enable), 1, 0, 0}, {"tlsrequire", store_yesno, ITEM(res_client.tls_require), 1, 0, 0}, {"tlscacertificatefile", store_dir, ITEM(res_client.tls_ca_certfile), 0, 0, 0}, @@ -245,15 +245,16 @@ void free_resource(RES *sres, int type) if (res->res_client.FDaddrs) { free_addresses(res->res_client.FDaddrs); } - if (res->res_client.pki_keypairfile) { - free(res->res_client.pki_keypairfile); + + if (res->res_client.pki_keypair_file) { + free(res->res_client.pki_keypair_file); } if (res->res_client.pki_keypair) { - crypto_keypair_free(res->res_client.pki_keypair); + crypto_keypair_free(res->res_client.pki_keypair); } - /* Also frees res_client.pki_keypair */ - if (res->res_client.pki_trustedkeys) { - delete res->res_client.pki_trustedkeys; + + if (res->res_client.pki_signing_key_files) { + delete res->res_client.pki_signing_key_files; } if (res->res_client.pki_signers) { X509_KEYPAIR *keypair; @@ -262,15 +263,17 @@ void free_resource(RES *sres, int type) } delete res->res_client.pki_signers; } - if (res->res_client.pki_masterkeys) { - delete res->res_client.pki_masterkeys; + + if (res->res_client.pki_master_key_files) { + delete res->res_client.pki_master_key_files; } - if (res->res_client.pki_readers) { + + if (res->res_client.pki_recipients) { X509_KEYPAIR *keypair; - foreach_alist(keypair, res->res_client.pki_readers) { + foreach_alist(keypair, res->res_client.pki_recipients) { crypto_keypair_free(keypair); } - delete res->res_client.pki_signers; + delete res->res_client.pki_recipients; } if (res->res_client.tls_ctx) { @@ -354,8 +357,12 @@ void save_resource(int type, RES_ITEM *items, int pass) if ((res = (URES *)GetResWithName(R_CLIENT, res_all.res_dir.hdr.name)) == NULL) { Emsg1(M_ABORT, 0, _("Cannot find Client resource %s\n"), res_all.res_dir.hdr.name); } - res->res_client.pki_trustedkeys = res_all.res_client.pki_trustedkeys; + res->res_client.pki_signing_key_files = res_all.res_client.pki_signing_key_files; + res->res_client.pki_master_key_files = res_all.res_client.pki_master_key_files; + res->res_client.pki_signers = res_all.res_client.pki_signers; + res->res_client.pki_recipients = res_all.res_client.pki_recipients; + res->res_client.messages = res_all.res_client.messages; break; default: diff --git a/bacula/src/filed/filed_conf.h b/bacula/src/filed/filed_conf.h index 5ba1737598..e8ea53b27b 100644 --- a/bacula/src/filed/filed_conf.h +++ b/bacula/src/filed/filed_conf.h @@ -73,9 +73,9 @@ struct CLIENT { uint32_t max_network_buffer_size; /* max network buf size */ int pki_sign; /* Enable Data Integrity Verification via Digital Signatures */ int pki_encrypt; /* Enable Data Encryption */ - char *pki_keypairfile; /* PKI Key Pair File */ - alist *pki_trustedkeys; /* PKI Trusted Public Keys */ - alist *pki_masterkeys; /* PKI Master Keys */ + char *pki_keypair_file; /* PKI Key Pair File */ + alist *pki_signing_key_files; /* PKI Signing Key Files */ + alist *pki_master_key_files; /* PKI Master Key Files */ int tls_enable; /* Enable TLS */ int tls_require; /* Require TLS */ char *tls_ca_certfile; /* TLS CA Certificate File */ @@ -85,7 +85,7 @@ struct CLIENT { X509_KEYPAIR *pki_keypair; /* Shared PKI Public/Private Keypair */ alist *pki_signers; /* Shared PKI Trusted Signers */ - alist *pki_readers; /* Shared PKI Recipients */ + alist *pki_recipients; /* Shared PKI Recipients */ TLS_CONTEXT *tls_ctx; /* Shared TLS Context */ }; diff --git a/bacula/src/filed/job.c b/bacula/src/filed/job.c index 57dd05eca2..56e43efcbf 100644 --- a/bacula/src/filed/job.c +++ b/bacula/src/filed/job.c @@ -177,7 +177,7 @@ void *handle_client_request(void *dirp) jcr->pki_encrypt = me->pki_encrypt; jcr->pki_keypair = me->pki_keypair; jcr->pki_signers = me->pki_signers; - jcr->pki_readers = me->pki_readers; + jcr->pki_recipients = me->pki_recipients; dir->jcr = jcr; enable_backup_privileges(NULL, 1 /* ignore_errors */); diff --git a/bacula/src/filed/restore.c b/bacula/src/filed/restore.c index 3ebd3ab4f4..f83ea81e41 100644 --- a/bacula/src/filed/restore.c +++ b/bacula/src/filed/restore.c @@ -83,6 +83,7 @@ void do_restore(JCR *jcr) uint64_t alt_addr = 0; /* Write address for alternative stream */ intmax_t alt_size = 0; /* Size of alternate stream */ SIGNATURE *sig = NULL; /* Cryptographic signature (if any) for file */ + CRYPTO_SESSION *cs = NULL; /* Cryptographic session data (if any) for file */ int flags; /* Options for extract_data() */ int stat; ATTR *attr; @@ -218,12 +219,22 @@ void do_restore(JCR *jcr) } else { Dmsg1(100, "Signature good on %s\n", jcr->last_fname); } - crypto_sign_free(sig); - sig = NULL; } else { Jmsg1(jcr, M_ERROR, 0, _("Missing cryptographic signature for %s\n"), jcr->last_fname); } } + + /* Free Signature */ + if (sig) { + crypto_sign_free(sig); + sig = NULL; + } + + if (cs) { + crypto_session_free(cs); + cs = NULL; + } + Dmsg0(30, "Stop extracting.\n"); } else if (is_bopen(&bfd)) { Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should not be open\n")); @@ -296,9 +307,24 @@ void do_restore(JCR *jcr) /* Data stream */ case STREAM_ENCRYPTED_SESSION_DATA: - // TODO landonf: Implement - // sig = crypto_sign_decode(sd->msg, (size_t) sd->msglen); Dmsg1(30, "Stream=Encrypted Session Data, size: %d\n", sd->msglen); + /* Save session keys . */ + switch(crypto_session_decode(sd->msg, (size_t) sd->msglen, jcr->pki_recipients, &cs)) { + case CRYPTO_ERROR_NONE: + /* Success */ + break; + case CRYPTO_ERROR_NORECIPIENT: + Jmsg(jcr, M_ERROR, 0, _("Missing private key required to decrypt encrypted backup data.")); + break; + case CRYPTO_ERROR_DECRYPTION: + Jmsg(jcr, M_ERROR, 0, _("Decrypt of the session key failed.")); + break; + default: + /* Shouldn't happen */ + Jmsg(jcr, M_ERROR, 0, _("An error occured while decoding encrypted session data stream.")); + break; + } + break; case STREAM_FILE_DATA: diff --git a/bacula/src/jcr.h b/bacula/src/jcr.h index 152bf65778..4134820639 100644 --- a/bacula/src/jcr.h +++ b/bacula/src/jcr.h @@ -236,7 +236,7 @@ public: DIGEST *digest; /* Last file's digest context */ X509_KEYPAIR *pki_keypair; /* Encryption key pair */ alist *pki_signers; /* Trusted Signers */ - alist *pki_readers; /* Trusted Readers */ + alist *pki_recipients; /* Trusted Recipients */ CRYPTO_SESSION *pki_session; /* PKE Public Keys + Symmetric Session Keys */ void *pki_session_encoded; /* Cached DER-encoded copy of pki_session */ size_t pki_session_encoded_size; /* Size of DER-encoded pki_session */ diff --git a/bacula/src/lib/crypto.c b/bacula/src/lib/crypto.c index fb5efbaa0b..9ce9818457 100644 --- a/bacula/src/lib/crypto.c +++ b/bacula/src/lib/crypto.c @@ -272,8 +272,7 @@ struct Signature { /* Encryption Session Data */ struct Crypto_Session { CryptoData *cryptoData; /* ASN.1 Structure */ - EVP_CIPHER *openssl_cipher; /* OpenSSL Cipher Object */ - unsigned char session_key[EVP_MAX_KEY_LENGTH]; /* Private symmetric session key */ + unsigned char *session_key; /* Private symmetric session key */ size_t session_key_len; /* Symmetric session key length */ }; @@ -461,6 +460,55 @@ static int crypto_pem_callback_dispatch (char *buf, int size, int rwflag, void * return (ctx->pem_callback(buf, size, ctx->pem_userdata)); } +/* + * Check a PEM-encoded file + * for the existence of a private key. + * Returns: true if a private key is found + * false otherwise + */ +bool crypto_keypair_has_key (const char *file) { + BIO *bio; + char *name = NULL; + char *header = NULL; + unsigned char *data = NULL; + bool retval = false; + long len; + + if (!(bio = BIO_new_file(file, "r"))) { + openssl_post_errors(M_ERROR, _("Unable to open private key file")); + return false; + } + + while (PEM_read_bio(bio, &name, &header, &data, &len)) { + /* We don't care what the data is, just that it's there */ + OPENSSL_free(header); + OPENSSL_free(data); + + /* + * PEM Header Found, check for a private key + * Due to OpenSSL limitations, we must specifically + * list supported PEM private key encodings. + */ + if (strcmp(name, PEM_STRING_RSA) == 0 + || strcmp(name, PEM_STRING_DSA) == 0 + || strcmp(name, PEM_STRING_PKCS8) == 0 + || strcmp(name, PEM_STRING_PKCS8INF) == 0) { + retval = true; + OPENSSL_free(name); + break; + } else { + OPENSSL_free(name); + } + } + + /* Free our bio */ + BIO_free(bio); + + /* Post PEM-decoding error messages, if any */ + openssl_post_errors(M_ERROR, _("Unable to read private key from file")); + return retval; +} + /* * Load a PEM-encoded private key. * Returns: true on success @@ -893,6 +941,10 @@ CRYPTO_SESSION *crypto_session_new (crypto_cipher_t cipher, alist *pubkeys) return NULL; } + /* Initialize required fields */ + cs->session_key = NULL; + + /* Allocate a CryptoData structure */ cs->cryptoData = CryptoData_new(); if (!cs->cryptoData) { @@ -936,6 +988,7 @@ CRYPTO_SESSION *crypto_session_new (crypto_cipher_t cipher, alist *pubkeys) /* Generate a symmetric session key */ cs->session_key_len = EVP_CIPHER_key_length(ec); + cs->session_key = (unsigned char *) malloc(cs->session_key_len); if (RAND_bytes(cs->session_key, cs->session_key_len) <= 0) { /* OpenSSL failure */ crypto_session_free(cs); @@ -955,6 +1008,7 @@ CRYPTO_SESSION *crypto_session_new (crypto_cipher_t cipher, alist *pubkeys) if (RAND_bytes(iv, iv_len) <= 0) { /* OpenSSL failure */ crypto_session_free(cs); + free(iv); return NULL; } @@ -962,8 +1016,10 @@ CRYPTO_SESSION *crypto_session_new (crypto_cipher_t cipher, alist *pubkeys) if (!M_ASN1_OCTET_STRING_set(cs->cryptoData->iv, iv, iv_len)) { /* Allocation failed in OpenSSL */ crypto_session_free(cs); + free(iv); return NULL; } + free(iv); } /* @@ -1054,11 +1110,15 @@ bool crypto_session_encode(CRYPTO_SESSION *cs, void *dest, size_t *length) * * Returns: CRYPTO_SESSION instance on success. * NULL on failure. + * Returns: CRYPTO_ERROR_NONE and a pointer to a newly allocated CRYPTO_SESSION structure in *session on success. + * A crypto_error_t value on failure. */ -// TODO landonf: Unimplemented, requires a private key to decrypt session key -CRYPTO_SESSION *crypto_session_decode(const void *data, size_t length) +crypto_error_t crypto_session_decode(const void *data, size_t length, alist *keypairs, CRYPTO_SESSION **session) { CRYPTO_SESSION *cs; + X509_KEYPAIR *keypair; + STACK_OF(RecipientInfo) *recipients; + crypto_error_t retval = CRYPTO_ERROR_NONE; #if (OPENSSL_VERSION_NUMBER >= 0x0090800FL) const unsigned char *p = (const unsigned char *) data; #else @@ -1067,7 +1127,7 @@ CRYPTO_SESSION *crypto_session_decode(const void *data, size_t length) cs = (CRYPTO_SESSION *) malloc(sizeof(CRYPTO_SESSION)); if (!cs) { - return NULL; + return CRYPTO_ERROR_INTERNAL; } /* d2i_CryptoData modifies the supplied pointer */ @@ -1076,10 +1136,67 @@ CRYPTO_SESSION *crypto_session_decode(const void *data, size_t length) if (!cs->cryptoData) { /* Allocation / Decoding failed in OpenSSL */ openssl_post_errors(M_ERROR, _("CryptoData decoding failed")); - return NULL; + retval = CRYPTO_ERROR_INTERNAL; + goto err; } - return cs; + recipients = cs->cryptoData->recipientInfo; + + /* + * Find a matching RecipientInfo structure for a supplied + * public key + */ + foreach_alist(keypair, keypairs) { + RecipientInfo *ri; + int i; + + /* Private key available? */ + if (keypair->privkey == NULL) { + continue; + } + + for (i = 0; i < sk_RecipientInfo_num(recipients); i++) { + ri = sk_RecipientInfo_value(recipients, i); + + /* Match against the subjectKeyIdentifier */ + if (M_ASN1_OCTET_STRING_cmp(keypair->keyid, ri->subjectKeyIdentifier) == 0) { + /* Match found, extract symmetric encryption session data */ + + /* RSA is required. */ + assert(EVP_PKEY_type(keypair->privkey->type) == EVP_PKEY_RSA); + + /* If we recieve a RecipientInfo structure that does not use + * RSA, return an error */ + if (OBJ_obj2nid(ri->keyEncryptionAlgorithm) != NID_rsaEncryption) { + retval = CRYPTO_ERROR_INVALID_CRYPTO; + goto err; + } + + /* Decrypt the session key */ + /* Allocate sufficient space for the largest possible decrypted data */ + cs->session_key = (unsigned char *) malloc(EVP_PKEY_size(keypair->privkey)); + cs->session_key_len = EVP_PKEY_decrypt(cs->session_key, M_ASN1_STRING_data(ri->encryptedKey), + M_ASN1_STRING_length(ri->encryptedKey), keypair->privkey); + + if (cs->session_key_len <= 0) { + openssl_post_errors(M_ERROR, _("Failure decrypting the session key")); + retval = CRYPTO_ERROR_DECRYPTION; + goto err; + } + + /* Session key successfully extracted, return the CRYPTO_SESSION structure */ + *session = cs; + return CRYPTO_ERROR_NONE; + } + } + } + + /* No matching recipient found */ + return CRYPTO_ERROR_NORECIPIENT; + +err: + crypto_session_free(cs); + return retval; } /* @@ -1087,7 +1204,12 @@ CRYPTO_SESSION *crypto_session_decode(const void *data, size_t length) */ void crypto_session_free (CRYPTO_SESSION *cs) { - CryptoData_free(cs->cryptoData); + if (cs->cryptoData) { + CryptoData_free(cs->cryptoData); + } + if (cs->session_key){ + free(cs->session_key); + } free(cs); } @@ -1274,13 +1396,14 @@ void crypto_sign_free (SIGNATURE *sig) { } X509_KEYPAIR *crypto_keypair_new (void) { return NULL; } X509_KEYPAIR *crypto_keypair_dup (X509_KEYPAIR *keypair) { return NULL; } int crypto_keypair_load_cert (X509_KEYPAIR *keypair, const char *file) { return false; } +bool crypto_keypair_has_key (const char *file) { return false; } int crypto_keypair_load_key (X509_KEYPAIR *keypair, const char *file, CRYPTO_PEM_PASSWD_CB *pem_callback, const void *pem_userdata) { return false; } void crypto_keypair_free (X509_KEYPAIR *keypair) { } CRYPTO_SESSION *crypto_session_new (crypto_cipher_t cipher, alist *pubkeys) { return NULL; } void crypto_session_free (CRYPTO_SESSION *cs) { } bool crypto_session_encode(CRYPTO_SESSION *cs, void *dest, size_t *length) { return false; } -CRYPTO_SESSION *crypto_session_decode(const void *data, size_t length) { return NULL; } +crypto_error_t crypto_session_decode(const void *data, size_t length, alist *keypairs, CRYPTO_SESSION **session) { return CRYPTO_ERROR_INTERNAL; } #endif /* HAVE_CRYPTO */ @@ -1347,10 +1470,16 @@ const char *crypto_strerror(crypto_error_t error) { return "No error"; case CRYPTO_ERROR_NOSIGNER: return "Signer not found"; + case CRYPTO_ERROR_NORECIPIENT: + return "Recipient not found"; case CRYPTO_ERROR_INVALID_DIGEST: return "Unsupported digest algorithm"; + case CRYPTO_ERROR_INVALID_CRYPTO: + return "Unsupported encryption algorithm"; case CRYPTO_ERROR_BAD_SIGNATURE: return "Signature is invalid"; + case CRYPTO_ERROR_DECRYPTION: + return "Decryption error"; case CRYPTO_ERROR_INTERNAL: /* This shouldn't happen */ return "Internal error"; diff --git a/bacula/src/lib/crypto.h b/bacula/src/lib/crypto.h index 04b8f934e8..f681f349c9 100644 --- a/bacula/src/lib/crypto.h +++ b/bacula/src/lib/crypto.h @@ -74,9 +74,12 @@ typedef enum { typedef enum { CRYPTO_ERROR_NONE = 0, /* No error */ CRYPTO_ERROR_NOSIGNER = 1, /* Signer not found */ - CRYPTO_ERROR_INVALID_DIGEST = 2, /* Unsupported digest algorithm */ - CRYPTO_ERROR_BAD_SIGNATURE = 3, /* Signature is invalid */ - CRYPTO_ERROR_INTERNAL = 4 /* Internal Error */ + CRYPTO_ERROR_NORECIPIENT = 2, /* Recipient not found */ + CRYPTO_ERROR_INVALID_DIGEST = 3, /* Unsupported digest algorithm */ + CRYPTO_ERROR_INVALID_CRYPTO = 4, /* Unsupported encryption algorithm */ + CRYPTO_ERROR_BAD_SIGNATURE = 5, /* Signature is invalid */ + CRYPTO_ERROR_DECRYPTION = 6, /* Decryption error */ + CRYPTO_ERROR_INTERNAL = 7 /* Internal Error */ } crypto_error_t; /* Message Digest Sizes */ diff --git a/bacula/src/lib/protos.h b/bacula/src/lib/protos.h index 7fdc4c574f..eb6d186345 100644 --- a/bacula/src/lib/protos.h +++ b/bacula/src/lib/protos.h @@ -130,10 +130,12 @@ void crypto_sign_free (SIGNATURE *sig); CRYPTO_SESSION * crypto_session_new (crypto_cipher_t cipher, alist *pubkeys); void crypto_session_free (CRYPTO_SESSION *cs); bool crypto_session_encode (CRYPTO_SESSION *cs, void *dest, size_t *length); +crypto_error_t crypto_session_decode (const void *data, size_t length, alist *keypairs, CRYPTO_SESSION **session); CRYPTO_SESSION * crypto_session_decode (const void *data, size_t length); X509_KEYPAIR * crypto_keypair_new (void); X509_KEYPAIR * crypto_keypair_dup (X509_KEYPAIR *keypair); int crypto_keypair_load_cert (X509_KEYPAIR *keypair, const char *file); +bool crypto_keypair_has_key (const char *file); int crypto_keypair_load_key (X509_KEYPAIR *keypair, const char *file, CRYPTO_PEM_PASSWD_CB *pem_callback, const void *pem_userdata); void crypto_keypair_free (X509_KEYPAIR *keypair); int crypto_default_pem_callback (char *buf, int size, const void *userdata); -- 2.39.2