#define TRUE 1
#define FALSE 0
+#ifndef MAX
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
#ifdef HAVE_TLS
#define have_tls 1
#else
#define STREAM_UNIX_ATTRIBUTES_ACCESS_ACL 15 /* Standard ACL attributes on UNIX */
#define STREAM_UNIX_ATTRIBUTES_DEFAULT_ACL 16 /* Default ACL attributes on UNIX */
/*** FIXME ***/
-#define STREAM_SHA256_DIGEST 17 /* SHA-256 digest for the file */
-#define STREAM_SHA512_DIGEST 18 /* SHA-512 digest for the file */
-#define STREAM_SIGNED_DIGEST 19 /* Signed File Digest, ASN.1, DER Encoded */
-#define STREAM_ENCRYPTED_FILE_DATA 20 /* Encrypted, uncompressed data */
-#define STREAM_ENCRYPTED_WIN32_DATA 21 /* Encrypted, uncompressed Win32 BackupRead data */
-#define STREAM_ENCRYPTED_SESSION_DATA 22 /* Encrypted Session Data, ASN.1, DER Encoded */
+#define STREAM_SHA256_DIGEST 17 /* SHA-256 digest for the file */
+#define STREAM_SHA512_DIGEST 18 /* SHA-512 digest for the file */
+#define STREAM_SIGNED_DIGEST 19 /* Signed File Digest, ASN.1, DER Encoded */
+#define STREAM_ENCRYPTED_FILE_DATA 20 /* Encrypted, uncompressed data */
+#define STREAM_ENCRYPTED_WIN32_DATA 21 /* Encrypted, uncompressed Win32 BackupRead data */
+#define STREAM_ENCRYPTED_SESSION_DATA 22 /* Encrypted Session Data, ASN.1, DER Encoded */
+#define STREAM_ENCRYPTED_FILE_GZIP_DATA 23 /* Encrypted, compressed data */
+#define STREAM_ENCRYPTED_WIN32_GZIP_DATA 24 /* Encrypted, compressed Win32 BackupRead data */
+#define STREAM_ENCRYPTED_MACOS_FORK_DATA 25 /* Encrypted, uncompressed Mac resource fork */
/*
/* ... and store the encoded size */
jcr->pki_session_encoded_size = size;
+
+ /* Allocate the encryption/decryption buffer */
+ jcr->crypto_buf = get_memory(CRYPTO_CIPHER_MAX_BLOCK_SIZE);
}
Dmsg1(300, "set_find_options ff=%p\n", jcr->ff);
free_pool_memory(jcr->compress_buf);
jcr->compress_buf = NULL;
}
+ if (jcr->crypto_buf) {
+ free_pool_memory(jcr->crypto_buf);
+ jcr->crypto_buf = NULL;
+ }
if (jcr->pki_session) {
crypto_session_free(jcr->pki_session);
if (jcr->pki_sign) {
signing_digest = crypto_digest_new(signing_algorithm);
}
-
/* Full-stop if a failure occured initializing the signature digest */
if (jcr->pki_sign && signing_digest == NULL) {
Jmsg(jcr, M_NOTSAVED, 0, _("%s signature digest initialization failed\n"),
return 1;
}
+ /* Enable encryption */
+ if (jcr->pki_encrypt) {
+ ff_pkt->flags |= FO_ENCRYPT;
+ }
+
/* Initialise the file descriptor we use for data and other streams. */
binit(&ff_pkt->bfd);
if (ff_pkt->flags & FO_PORTABLE) {
char *rbuf, *wbuf;
int rsize = jcr->buf_size; /* read buffer size */
POOLMEM *msgsave;
+ CIPHER_CONTEXT *cipher_ctx = NULL; /* Quell bogus uninitialized warnings */
+ const void *cipher_input;
+ size_t cipher_input_len;
+ size_t cipher_block_size;
+ size_t encrypted_len;
#ifdef FD_NO_SEND_TEST
return 1;
#endif
msgsave = sd->msg;
rbuf = sd->msg; /* read buffer */
wbuf = sd->msg; /* write buffer */
+ cipher_input = rbuf; /* encrypt uncompressed data */
Dmsg1(300, "Saving data, type=%d\n", ff_pkt->type);
-
#ifdef HAVE_LIBZ
uLong compress_len, max_compress_len = 0;
const Bytef *cbuf = NULL;
max_compress_len = jcr->compress_buf_size; /* set max length */
}
wbuf = jcr->compress_buf; /* compressed output here */
+ cipher_input = jcr->compress_buf; /* encrypt compressed data */
}
#endif
+ if (ff_pkt->flags & FO_ENCRYPT) {
+ /* Allocate the cipher context */
+ if ((cipher_ctx = crypto_cipher_new(jcr->pki_session, true, &cipher_block_size)) == NULL) {
+ /* Shouldn't happen! */
+ Jmsg0(jcr, M_FATAL, 0, _("Failed to initialize encryption context"));
+ goto err;
+ }
+
+ /*
+ * Grow the crypto buffer, if necessary.
+ * crypto_cipher_update() will buffer up to (cipher_block_size - 1).
+ * We grow crypto_buf to the maximum number of blocks that
+ * could be returned for the given read buffer size.
+ * (Using the larger of either rsize or max_compress_len)
+ */
+ jcr->crypto_buf = check_pool_memory_size(jcr->crypto_buf, (MAX((size_t) rsize, max_compress_len) + cipher_block_size - 1) / cipher_block_size * cipher_block_size);
+
+ wbuf = jcr->crypto_buf; /* Encrypted, possibly compressed output here. */
+ }
+
/*
* Send Data header to Storage daemon
* <file-index> <stream> <info>
if (!bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, stream)) {
Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
bnet_strerror(sd));
- return 0;
+ goto err;
}
Dmsg1(300, ">stored: datahdr %s\n", sd->msg);
jcr->ReadBytes += sd->msglen; /* count bytes read */
fileAddr += sd->msglen;
+ /* Uncompressed cipher input length */
+ cipher_input_len = sd->msglen;
+
/* Update checksum if requested */
if (digest) {
crypto_digest_update(digest, rbuf, sd->msglen);
(const Bytef *)rbuf, (uLong)sd->msglen,
ff_pkt->GZIP_level)) != Z_OK) {
Jmsg(jcr, M_FATAL, 0, _("Compression error: %d\n"), zstat);
- sd->msg = msgsave;
- sd->msglen = 0;
set_jcr_job_status(jcr, JS_ErrorTerminated);
- return 0;
+ goto err;
}
Dmsg2(400, "compressed len=%d uncompressed len=%d\n",
compress_len, sd->msglen);
sd->msglen = compress_len; /* set compressed length */
+ cipher_input_len = compress_len;
}
#endif
+ if (ff_pkt->flags & FO_ENCRYPT) {
+ /* Encrypt the input block */
+ if (crypto_cipher_update(cipher_ctx, cipher_input, cipher_input_len, jcr->crypto_buf, &encrypted_len)) {
+ if (encrypted_len == 0) {
+ /* No full block of data available, read more data */
+ continue;
+ }
+ Dmsg2(400, "encrypted len=%d unencrypted len=%d\n",
+ encrypted_len, sd->msglen);
+ sd->msglen = encrypted_len; /* set encrypted length */
+ } else {
+ /* Encryption failed. Shouldn't happen. */
+ Jmsg(jcr, M_FATAL, 0, _("Encryption error\n"));
+ goto err;
+ }
+ }
+
/* Send the buffer to the Storage daemon */
if (!sparseBlock) {
if (ff_pkt->flags & FO_SPARSE) {
if (!bnet_send(sd)) {
Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
bnet_strerror(sd));
- sd->msg = msgsave; /* restore bnet buffer */
- sd->msglen = 0;
- return 0;
+ goto err;
}
}
Dmsg1(130, "Send data to SD len=%d\n", sd->msglen);
/* #endif */
- jcr->JobBytes += sd->msglen; /* count bytes saved possibly compressed */
+ jcr->JobBytes += sd->msglen; /* count bytes saved possibly compressed/encrypted */
sd->msg = msgsave; /* restore read buffer */
} /* end while read file data */
+ /* Send any remaining encrypted data + padding */
+ if (ff_pkt->flags & FO_ENCRYPT) {
+ if (!crypto_cipher_finalize(cipher_ctx, jcr->crypto_buf, &encrypted_len)) {
+ /* Padding failed. Shouldn't happen. */
+ Jmsg(jcr, M_FATAL, 0, _("Encryption padding error\n"));
+ goto err;
+ }
+
+ if (encrypted_len > 0) {
+ sd->msglen = encrypted_len; /* set encrypted length */
+
+ /* Send remaining encrypted data to the SD */
+ if (ff_pkt->flags & FO_SPARSE) {
+ sd->msglen += SPARSE_FADDR_SIZE; /* include fileAddr in size */
+ }
+ sd->msg = wbuf; /* set correct write buffer */
+ if (!bnet_send(sd)) {
+ Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
+ bnet_strerror(sd));
+ goto err;
+ }
+ Dmsg1(130, "Send data to SD len=%d\n", sd->msglen);
+ jcr->JobBytes += sd->msglen; /* count bytes saved possibly compressed/encrypted */
+ sd->msg = msgsave; /* restore bnet buffer */
+ }
+ }
if (sd->msglen < 0) {
berrno be;
if (!bnet_sig(sd, BNET_EOD)) { /* indicate end of file data */
Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
bnet_strerror(sd));
- return 0;
+ goto err;
+ }
+
+ /* Free the cipher context */
+ if (cipher_ctx) {
+ crypto_cipher_free(cipher_ctx);
}
return 1;
+
+err:
+ if (cipher_ctx) {
+ crypto_cipher_free(cipher_ctx);
+ }
+ sd->msg = msgsave; /* restore bnet buffer */
+ sd->msglen = 0;
+ return 0;
}
/*
#endif
/* Find what data stream we will use, then encode the attributes */
- data_stream = select_data_stream(ff_pkt);
+ if ((data_stream = select_data_stream(ff_pkt)) == STREAM_NONE) {
+ /* This should not happen */
+ Jmsg0(jcr, M_FATAL, 0, _("Invalid file flags, no supported data stream type.\n"));
+ return false;
+ }
encode_stat(attribs, ff_pkt, data_stream);
/* Now possibly extend the attributes */
case STREAM_GZIP_DATA:
case STREAM_SPARSE_GZIP_DATA:
case STREAM_WIN32_GZIP_DATA:
+ case STREAM_ENCRYPTED_FILE_DATA:
+ case STREAM_ENCRYPTED_WIN32_DATA:
+ case STREAM_ENCRYPTED_FILE_GZIP_DATA:
+ case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
/* Force an expected, consistent stream type here */
if (extract && (prev_stream == stream || prev_stream == STREAM_UNIX_ATTRIBUTES
|| prev_stream == STREAM_UNIX_ATTRIBUTES_EX
|| prev_stream == STREAM_ENCRYPTED_SESSION_DATA)) {
flags = 0;
+
if (stream == STREAM_SPARSE_DATA || stream == STREAM_SPARSE_GZIP_DATA) {
flags |= FO_SPARSE;
}
+
if (stream == STREAM_GZIP_DATA || stream == STREAM_SPARSE_GZIP_DATA
- || stream == STREAM_WIN32_GZIP_DATA) {
+ || stream == STREAM_WIN32_GZIP_DATA || stream == STREAM_ENCRYPTED_FILE_GZIP_DATA
+ || stream == STREAM_ENCRYPTED_WIN32_GZIP_DATA) {
flags |= FO_GZIP;
}
/* Resource fork stream - only recorded after a file to be restored */
/* Silently ignore if we cannot write - we already reported that */
+ case STREAM_ENCRYPTED_MACOS_FORK_DATA:
case STREAM_MACOS_FORK_DATA:
#ifdef HAVE_DARWIN_OS
if (extract) {
{
int stream;
+ /*
+ * Fix all incompatible options
+ */
+
+ /* No sparse option for encrypted data */
+ if (ff_pkt->flags & FO_ENCRYPT) {
+ ff_pkt->flags &= ~FO_SPARSE;
+ }
+
/* Note, no sparse option for win32_data */
if (!is_portable_backup(&ff_pkt->bfd)) {
stream = STREAM_WIN32_DATA;
} else {
stream = STREAM_FILE_DATA;
}
+
+ /* Encryption is only supported for file data */
+ if (stream != STREAM_FILE_DATA && stream != STREAM_WIN32_DATA &&
+ stream != STREAM_MACOS_FORK_DATA) {
+ ff_pkt->flags &= ~FO_ENCRYPT;
+ }
+
+ /* Compression is not supported for Mac fork data */
+ if (stream == STREAM_MACOS_FORK_DATA) {
+ ff_pkt->flags &= ~FO_GZIP;
+ }
+
+ /*
+ * Handle compression and encryption options
+ */
#ifdef HAVE_LIBZ
if (ff_pkt->flags & FO_GZIP) {
- if (stream == STREAM_WIN32_DATA) {
+ switch (stream) {
+ case STREAM_WIN32_DATA:
stream = STREAM_WIN32_GZIP_DATA;
- } else if (stream == STREAM_FILE_DATA) {
- stream = STREAM_GZIP_DATA;
- } else {
+ break;
+ case STREAM_SPARSE_DATA:
stream = STREAM_SPARSE_GZIP_DATA;
+ break;
+ case STREAM_FILE_DATA:
+ stream = STREAM_GZIP_DATA;
+ break;
+ default:
+ /* All stream types that do not support gzip should clear out
+ * FO_GZIP above, and this code block should be unreachable. */
+ ASSERT(!ff_pkt->flags & FO_GZIP);
+ return STREAM_NONE;
}
}
#endif
+#ifdef HAVE_CRYPTO
+ if (ff_pkt->flags & FO_ENCRYPT) {
+ switch (stream) {
+ case STREAM_WIN32_DATA:
+ stream = STREAM_ENCRYPTED_WIN32_DATA;
+ break;
+ case STREAM_WIN32_GZIP_DATA:
+ stream = STREAM_ENCRYPTED_WIN32_GZIP_DATA;
+ break;
+ case STREAM_FILE_DATA:
+ stream = STREAM_ENCRYPTED_FILE_DATA;
+ break;
+ case STREAM_GZIP_DATA:
+ stream = STREAM_ENCRYPTED_FILE_GZIP_DATA;
+ break;
+ default:
+ /* All stream types that do not support encryption should clear out
+ * FO_ENCRYPT above, and this code block should be unreachable. */
+ ASSERT(!ff_pkt->flags & FO_ENCRYPT);
+ return STREAM_NONE;
+ }
+ }
+#endif
+
return stream;
}
switch (stream) {
case STREAM_WIN32_DATA:
case STREAM_WIN32_GZIP_DATA:
+ case STREAM_ENCRYPTED_WIN32_DATA:
+ case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
return true;
}
return false;
return _("SHA512 digest");
case STREAM_SIGNED_DIGEST:
return _("Signed digest");
+ case STREAM_ENCRYPTED_FILE_DATA:
+ return _("Encrypted File data");
+ case STREAM_ENCRYPTED_FILE_GZIP_DATA:
+ return _("Encrypted GZIP data");
+ case STREAM_ENCRYPTED_WIN32_DATA:
+ return _("Encrypted Win32 data");
+ case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
+ return _("Encrypted Win32 GZIP data");
+ case STREAM_ENCRYPTED_MACOS_FORK_DATA:
+ return _("Encrypted HFS+ resource fork");
default:
sprintf(buf, "%d", stream);
return (const char *)buf;
#endif
case STREAM_MACOS_FORK_DATA:
case STREAM_HFSPLUS_ATTRIBUTES:
+ case STREAM_ENCRYPTED_MACOS_FORK_DATA:
return false;
/* Known streams */
#endif
#ifdef HAVE_CRYPTO
case STREAM_SIGNED_DIGEST:
+ case STREAM_ENCRYPTED_FILE_DATA:
+ case STREAM_ENCRYPTED_FILE_GZIP_DATA:
+ case STREAM_ENCRYPTED_WIN32_DATA:
+ case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
#endif
case 0: /* compatibility with old tapes */
return true;
case STREAM_SHA256_DIGEST:
case STREAM_SHA512_DIGEST:
#endif
+#ifdef HAVE_CRYPTO
+ case STREAM_SIGNED_DIGEST:
+ case STREAM_ENCRYPTED_FILE_DATA:
+ case STREAM_ENCRYPTED_FILE_GZIP_DATA:
+ case STREAM_ENCRYPTED_WIN32_DATA:
+ case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
+#endif
#ifdef HAVE_DARWIN_OS
case STREAM_MACOS_FORK_DATA:
case STREAM_HFSPLUS_ATTRIBUTES:
-#endif
+#ifdef HAVE_CRYPTO
+ case STREAM_ENCRYPTED_MACOS_FORK_DATA:
+#endif /* HAVE_CRYPTO */
+#endif /* HAVE_DARWIN_OS */
case 0: /* compatibility with old tapes */
return true;
#define FO_WIN32DECOMP (1<<18) /* Use BackupRead decomposition */
#define FO_SHA256 (1<<19) /* Do SHA256 checksum */
#define FO_SHA512 (1<<20) /* Do SHA512 checksum */
+#define FO_ENCRYPT (1<<21) /* Encrypt data stream */
struct s_included_file {
struct s_included_file *next;
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 */
+ POOLMEM *crypto_buf; /* Encryption/Decryption buffer */
DIRRES* director; /* Director resource */
#endif /* FILE_DAEMON */
size_t session_key_len; /* Symmetric session key length */
};
+/* Symmetric Cipher Context */
+struct Cipher_Context {
+ EVP_CIPHER_CTX ctx;
+};
+
/* PEM Password Dispatch Context */
typedef struct PEM_CB_Context {
CRYPTO_PEM_PASSWD_CB *pem_callback;
free(cs);
}
+/*
+ * Create a new crypto cipher context with the specified session object
+ * Returns: A pointer to a CIPHER_CONTEXT object on success. The cipher block size is returned in blocksize.
+ * NULL on failure.
+ */
+CIPHER_CONTEXT *crypto_cipher_new (CRYPTO_SESSION *cs, bool encrypt, size_t *blocksize)
+{
+ CIPHER_CONTEXT *cipher_ctx;
+ const EVP_CIPHER *ec;
+
+ cipher_ctx = (CIPHER_CONTEXT *) malloc(sizeof(CIPHER_CONTEXT));
+ if (!cipher_ctx) {
+ return NULL;
+ }
+
+ /*
+ * Acquire a cipher instance for the given ASN.1 cipher NID
+ */
+ if ((ec = EVP_get_cipherbyobj(cs->cryptoData->contentEncryptionAlgorithm)) == NULL) {
+ Emsg1(M_ERROR, 0, _("Unsupported contentEncryptionAlgorithm: %d\n"), OBJ_obj2nid(cs->cryptoData->contentEncryptionAlgorithm));
+ crypto_cipher_free(cipher_ctx);
+ return NULL;
+ }
+
+ /* Initialize the OpenSSL cipher context */
+ EVP_CIPHER_CTX_init(&cipher_ctx->ctx);
+ if (encrypt) {
+ /* Initialize for encryption */
+ if (!EVP_CipherInit_ex(&cipher_ctx->ctx, ec, NULL, NULL, NULL, 1)) {
+ openssl_post_errors(M_ERROR, _("OpenSSL cipher context initialization failed"));
+ goto err;
+ }
+ } else {
+ /* Initialize for decryption */
+ if (!EVP_CipherInit_ex(&cipher_ctx->ctx, ec, NULL, NULL, NULL, 0)) {
+ openssl_post_errors(M_ERROR, _("OpenSSL cipher context initialization failed"));
+ goto err;
+ }
+ }
+
+ /* Set the key size */
+ if (!EVP_CIPHER_CTX_set_key_length(&cipher_ctx->ctx, cs->session_key_len)) {
+ openssl_post_errors(M_ERROR, _("Encryption session provided an invalid symmetric key"));
+ goto err;
+ }
+
+ /* Validate the IV length */
+ if (EVP_CIPHER_iv_length(ec) != M_ASN1_STRING_length(cs->cryptoData->iv)) {
+ openssl_post_errors(M_ERROR, _("Encryption session provided an invalid IV"));
+ goto err;
+ }
+
+ /* Add the key and IV to the cipher context */
+ if (!EVP_CipherInit_ex(&cipher_ctx->ctx, NULL, NULL, cs->session_key, M_ASN1_STRING_data(cs->cryptoData->iv), -1)) {
+ openssl_post_errors(M_ERROR, _("OpenSSL cipher context key/IV initialization failed"));
+ goto err;
+ }
+
+ *blocksize = EVP_CIPHER_CTX_block_size(&cipher_ctx->ctx);
+ return cipher_ctx;
+
+err:
+ crypto_cipher_free(cipher_ctx);
+ return NULL;
+}
+
+
+/*
+ * Encrypt/Decrypt length bytes of data using the provided cipher context
+ * Returns: true on success, number of bytes output in written
+ * false on failure
+ */
+bool crypto_cipher_update (CIPHER_CONTEXT *cipher_ctx, const void *data, size_t length, const void *dest, size_t *written) {
+ if (!EVP_CipherUpdate(&cipher_ctx->ctx, (unsigned char *) dest, (int *) written, (const unsigned char *) data, length)) {
+ /* This really shouldn't fail */
+ return false;
+ } else {
+ return true;
+ }
+}
+
+/*
+ * Finalize the cipher context, writing any remaining data and necessary padding
+ * to dest, and the size in written.
+ * The result size will either be one block of data or zero.
+ *
+ * Returns: true on success
+ * false on failure
+ */
+bool crypto_cipher_finalize (CIPHER_CONTEXT *cipher_ctx, void *dest, size_t *written) {
+ if (!EVP_CipherFinal_ex(&cipher_ctx->ctx, (unsigned char *) dest, (int *) written)) {
+ /* This really shouldn't fail */
+ return false;
+ } else {
+ return true;
+ }
+}
+
+
+/*
+ * Free memory associated with a cipher context.
+ */
+void crypto_cipher_free (CIPHER_CONTEXT *cipher_ctx)
+{
+ EVP_CIPHER_CTX_cleanup(&cipher_ctx->ctx);
+ free (cipher_ctx);
+}
+
+
/*
* Perform global initialization of OpenSSL
* This function is not thread safe.
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_error_t crypto_session_decode(const void *data, size_t length, alist *keypairs, CRYPTO_SESSION **session) { return CRYPTO_ERROR_INTERNAL; }
+bool crypto_session_encode (CRYPTO_SESSION *cs, void *dest, size_t *length) { return false; }
+crypto_error_t crypto_session_decode (const void *data, size_t length, alist *keypairs, CRYPTO_SESSION **session) { return CRYPTO_ERROR_INTERNAL; }
+
+CIPHER_CONTEXT *crypto_cipher_new (CRYPTO_SESSION *cs, bool encrypt, size_t *blocksize) { return NULL; }
+bool crypto_cipher_update (CIPHER_CONTEXT *cipher_ctx, const void *data, size_t length, const void *dest, size_t *written) { return false; }
+bool crypto_cipher_finalize (CIPHER_CONTEXT *cipher_ctx, void *dest, size_t *written) { return false; }
+void crypto_cipher_free (CIPHER_CONTEXT *cipher_ctx) { }
#endif /* HAVE_CRYPTO */
/* Opaque PKI Symmetric Key Data Structure */
typedef struct Crypto_Session CRYPTO_SESSION;
+/* Opaque Encryption/Decryption Context Structure */
+typedef struct Cipher_Context CIPHER_CONTEXT;
+
/* PEM Decryption Passphrase Callback */
typedef int (CRYPTO_PEM_PASSWD_CB) (char *buf, int size, const void *userdata);
/* Maximum Message Digest Size */
#ifdef HAVE_OPENSSL
-/* Let OpenSSL define it */
-#define CRYPTO_DIGEST_MAX_SIZE EVP_MAX_MD_SIZE
+/* Let OpenSSL define a few things */
+#define CRYPTO_DIGEST_MAX_SIZE EVP_MAX_MD_SIZE
+#define CRYPTO_CIPHER_MAX_BLOCK_SIZE EVP_MAX_BLOCK_LENGTH
#else /* HAVE_OPENSSL */
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);
+CIPHER_CONTEXT * crypto_cipher_new (CRYPTO_SESSION *cs, bool encrypt, size_t *blocksize);
+bool crypto_cipher_update (CIPHER_CONTEXT *cipher_ctx, const void *data, size_t length, const void *dest, size_t *written);
+bool crypto_cipher_finalize (CIPHER_CONTEXT *cipher_ctx, void *dest, size_t *written);
+void crypto_cipher_free (CIPHER_CONTEXT *cipher_ctx);
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);
return "SIGNED-DIGEST";
case STREAM_ENCRYPTED_SESSION_DATA:
return "ENCRYPTED-SESSION-DATA";
+ case STREAM_ENCRYPTED_FILE_DATA:
+ return "ENCRYPTED-FILE";
+ case STREAM_ENCRYPTED_FILE_GZIP_DATA:
+ return "ENCRYPTED-GZIP";
+ case STREAM_ENCRYPTED_WIN32_DATA:
+ return "ENCRYPTED-WIN32-DATA";
+ case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
+ return "ENCRYPTED-WIN32-GZIP";
+ case STREAM_ENCRYPTED_MACOS_FORK_DATA:
+ return "ENCRYPTED-MACOS-RSRC";
case -STREAM_UNIX_ATTRIBUTES:
return "contUATTR";
case -STREAM_FILE_DATA:
return "contSIGNED-DIGEST";
case -STREAM_ENCRYPTED_SESSION_DATA:
return "contENCRYPTED-SESSION-DATA";
+ case -STREAM_ENCRYPTED_FILE_DATA:
+ return "contENCRYPTED-FILE";
+ case -STREAM_ENCRYPTED_FILE_GZIP_DATA:
+ return "contENCRYPTED-GZIP";
+ case -STREAM_ENCRYPTED_WIN32_DATA:
+ return "contENCRYPTED-WIN32-DATA";
+ case -STREAM_ENCRYPTED_WIN32_GZIP_DATA:
+ return "contENCRYPTED-WIN32-GZIP";
+ case -STREAM_ENCRYPTED_MACOS_FORK_DATA:
+ return "contENCRYPTED-MACOS-RSRC";
default:
sprintf(buf, "%d", stream);
return buf;