]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/lib/crypto.c
Tweak version date
[bacula/bacula] / bacula / src / lib / crypto.c
index b5cd07c12a7ba9b05184b8537ef7d56c41f38e34..7ffa20ecc52227bbea2e33bf75424b996ede3456 100644 (file)
@@ -1,26 +1,26 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2005-2007 Free Software Foundation Europe e.V.
+   Copyright (C) 2005-2011 Free Software Foundation Europe e.V.
 
    The main author of Bacula is Kern Sibbald, with contributions from
    many others, a complete list can be found in the file AUTHORS.
    This program is Free Software; you can redistribute it and/or
-   modify it under the terms of version two of the GNU General Public
-   License as published by the Free Software Foundation plus additions
-   that are listed in the file LICENSE.
+   modify it under the terms of version three of the GNU Affero General Public
+   License as published by the Free Software Foundation and included
+   in the file LICENSE.
 
    This program is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    General Public License for more details.
 
-   You should have received a copy of the GNU General Public License
+   You should have received a copy of the GNU Affero General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Bacula® is a registered trademark of John Walker.
+   Bacula® is a registered trademark of Kern Sibbald.
    The licensor of Bacula is the Free Software Foundation Europe
    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
    Switzerland, email:ftf@fsfeurope.org.
@@ -30,8 +30,6 @@
  *
  * Author: Landon Fuller <landonf@opendarwin.org>
  *
- * Version $Id$
- *
  * This file was contributed to the Bacula project by Landon Fuller.
  *
  * Landon Fuller has been granted a perpetual, worldwide, non-exclusive,
 #include "jcr.h"
 #include <assert.h>
 
+/**
+ * For OpenSSL version 1.x, EVP_PKEY_encrypt no longer
+ *  exists.  It was not an official API.
+ */
+#ifdef HAVE_OPENSSLv1
+#define EVP_PKEY_encrypt EVP_PKEY_encrypt_old
+#define EVP_PKEY_decrypt EVP_PKEY_decrypt_old
+#endif
+
 /*
  * Bacula ASN.1 Syntax
  *
@@ -309,7 +316,7 @@ typedef struct PEM_CB_Context {
  */
 static ASN1_OCTET_STRING *openssl_cert_keyid(X509 *cert) {
    X509_EXTENSION *ext;
-   X509V3_EXT_METHOD *method;
+   const X509V3_EXT_METHOD *method;
    ASN1_OCTET_STRING *keyid;
    int i;
 #if (OPENSSL_VERSION_NUMBER >= 0x0090800FL)
@@ -362,14 +369,12 @@ static ASN1_OCTET_STRING *openssl_cert_keyid(X509 *cert) {
  *  Returns: A pointer to a X509 KEYPAIR object on success.
  *           NULL on failure.
  */
-X509_KEYPAIR *crypto_keypair_new(void) {
+X509_KEYPAIR *crypto_keypair_new(void) 
+{
    X509_KEYPAIR *keypair;
 
    /* Allocate our keypair structure */
-   keypair = (X509_KEYPAIR *) malloc(sizeof(X509_KEYPAIR));
-   if (!keypair) {
-      return NULL;
-   }
+   keypair = (X509_KEYPAIR *)malloc(sizeof(X509_KEYPAIR));
 
    /* Initialize our keypair structure */
    keypair->keyid = NULL;
@@ -453,13 +458,15 @@ int crypto_keypair_load_cert(X509_KEYPAIR *keypair, const char *file)
 
    /* Extract the subjectKeyIdentifier extension field */
    if ((keypair->keyid = openssl_cert_keyid(cert)) == NULL) {
-      Emsg0(M_ERROR, 0, _("Provided certificate does not include the required subjectKeyIdentifier extension."));
+      Jmsg0(NULL, M_ERROR, 0,
+         _("Provided certificate does not include the required subjectKeyIdentifier extension."));
       goto err;
    }
 
    /* Validate the public key type (only RSA is supported) */
    if (EVP_PKEY_type(keypair->pubkey->type) != EVP_PKEY_RSA) {
-       Emsg1(M_ERROR, 0, _("Unsupported key type provided: %d\n"), EVP_PKEY_type(keypair->pubkey->type));
+       Jmsg1(NULL, M_ERROR, 0, 
+             _("Unsupported key type provided: %d\n"), EVP_PKEY_type(keypair->pubkey->type));
        goto err;
    }
 
@@ -597,6 +604,7 @@ DIGEST *crypto_digest_new(JCR *jcr, crypto_digest_t type)
    digest = (DIGEST *)malloc(sizeof(DIGEST));
    digest->type = type;
    digest->jcr = jcr;
+   Dmsg1(150, "crypto_digest_new jcr=%p\n", jcr);
 
    /* Initialize the OpenSSL message digest context */
    EVP_MD_CTX_init(&digest->ctx);
@@ -631,6 +639,7 @@ DIGEST *crypto_digest_new(JCR *jcr, crypto_digest_t type)
 
 err:
    /* This should not happen, but never say never ... */
+   Dmsg0(150, "Digest init failed.\n");
    openssl_post_errors(jcr, M_ERROR, _("OpenSSL digest initialization failed"));
    crypto_digest_free(digest);
    return NULL;
@@ -644,6 +653,7 @@ err:
 bool crypto_digest_update(DIGEST *digest, const uint8_t *data, uint32_t length)
 {
    if (EVP_DigestUpdate(&digest->ctx, data, length) == 0) {
+      Dmsg0(150, "digest update failed\n");
       openssl_post_errors(digest->jcr, M_ERROR, _("OpenSSL digest update failed"));
       return false;
    } else { 
@@ -661,6 +671,7 @@ bool crypto_digest_update(DIGEST *digest, const uint8_t *data, uint32_t length)
 bool crypto_digest_finalize(DIGEST *digest, uint8_t *dest, uint32_t *length)
 {
    if (!EVP_DigestFinal(&digest->ctx, dest, (unsigned int *)length)) {
+      Dmsg0(150, "digest finalize failed\n");
       openssl_post_errors(digest->jcr, M_ERROR, _("OpenSSL digest finalize failed"));
       return false;
    } else {
@@ -693,6 +704,7 @@ SIGNATURE *crypto_sign_new(JCR *jcr)
 
    sig->sigData = SignatureData_new();
    sig->jcr = jcr;
+   Dmsg1(150, "crypto_sign_new jcr=%p\n", jcr);
 
    if (!sig->sigData) {
       /* Allocation failed in OpenSSL */
@@ -708,11 +720,13 @@ SIGNATURE *crypto_sign_new(JCR *jcr)
 
 /*
  * For a given public key, find the associated SignatureInfo record
- * and create a digest context for signature validation
+ *   and create a digest context for signature validation
+ *
  * Returns: CRYPTO_ERROR_NONE on success, with the newly allocated DIGEST in digest.
  *          A crypto_error_t value on failure.
  */
-crypto_error_t crypto_sign_get_digest(SIGNATURE *sig, X509_KEYPAIR *keypair, DIGEST **digest)
+crypto_error_t crypto_sign_get_digest(SIGNATURE *sig, X509_KEYPAIR *keypair, 
+                                      crypto_digest_t &type, DIGEST **digest)
 {
    STACK_OF(SignerInfo) *signers;
    SignerInfo *si;
@@ -724,22 +738,32 @@ crypto_error_t crypto_sign_get_digest(SIGNATURE *sig, X509_KEYPAIR *keypair, DIG
       si = sk_SignerInfo_value(signers, i);
       if (M_ASN1_OCTET_STRING_cmp(keypair->keyid, si->subjectKeyIdentifier) == 0) {
          /* Get the digest algorithm and allocate a digest context */
+         Dmsg1(150, "crypto_sign_get_digest jcr=%p\n", sig->jcr);
          switch (OBJ_obj2nid(si->digestAlgorithm)) {
          case NID_md5:
+            Dmsg0(100, "sign digest algorithm is MD5\n");
+            type = CRYPTO_DIGEST_MD5;
             *digest = crypto_digest_new(sig->jcr, CRYPTO_DIGEST_MD5);
             break;
          case NID_sha1:
+            Dmsg0(100, "sign digest algorithm is SHA1\n");
+            type = CRYPTO_DIGEST_SHA1;
             *digest = crypto_digest_new(sig->jcr, CRYPTO_DIGEST_SHA1);
             break;
 #ifdef HAVE_SHA2
          case NID_sha256:
+            Dmsg0(100, "sign digest algorithm is SHA256\n");
+            type = CRYPTO_DIGEST_SHA256;
             *digest = crypto_digest_new(sig->jcr, CRYPTO_DIGEST_SHA256);
             break;
          case NID_sha512:
+            Dmsg0(100, "sign digest algorithm is SHA512\n");
+            type = CRYPTO_DIGEST_SHA512;
             *digest = crypto_digest_new(sig->jcr, CRYPTO_DIGEST_SHA512);
             break;
 #endif
          default:
+            type = CRYPTO_DIGEST_NONE;
             *digest = NULL;
             return CRYPTO_ERROR_INVALID_DIGEST;
          }
@@ -919,7 +943,7 @@ int crypto_sign_encode(SIGNATURE *sig, uint8_t *dest, uint32_t *length)
 
  */
 
-SIGNATURE *crypto_sign_decode(const uint8_t *sigData, uint32_t length)
+SIGNATURE *crypto_sign_decode(JCR *jcr, const uint8_t *sigData, uint32_t length)
 {
    SIGNATURE *sig;
 #if (OPENSSL_VERSION_NUMBER >= 0x0090800FL)
@@ -932,13 +956,14 @@ SIGNATURE *crypto_sign_decode(const uint8_t *sigData, uint32_t length)
    if (!sig) {
       return NULL;
    }
+   sig->jcr = jcr;
 
    /* d2i_SignatureData modifies the supplied pointer */
    sig->sigData  = d2i_SignatureData(NULL, &p, length);
 
    if (!sig->sigData) {
       /* Allocation / Decoding failed in OpenSSL */
-      openssl_post_errors(M_ERROR, _("Signature decoding failed"));
+      openssl_post_errors(jcr, M_ERROR, _("Signature decoding failed"));
       free(sig);
       return NULL;
    }
@@ -959,6 +984,8 @@ void crypto_sign_free(SIGNATURE *sig)
  * Create a new encryption session.
  *  Returns: A pointer to a CRYPTO_SESSION object on success.
  *           NULL on failure.
+ *
+ *  Note! Bacula malloc() fails if out of memory.
  */
 CRYPTO_SESSION *crypto_session_new (crypto_cipher_t cipher, alist *pubkeys)
 {
@@ -969,10 +996,7 @@ CRYPTO_SESSION *crypto_session_new (crypto_cipher_t cipher, alist *pubkeys)
    int iv_len;
 
    /* Allocate our session description structures */
-   cs = (CRYPTO_SESSION *) malloc(sizeof(CRYPTO_SESSION));
-   if (!cs) {
-      return NULL;
-   }
+   cs = (CRYPTO_SESSION *)malloc(sizeof(CRYPTO_SESSION));
 
    /* Initialize required fields */
    cs->session_key = NULL;
@@ -998,6 +1022,7 @@ CRYPTO_SESSION *crypto_session_new (crypto_cipher_t cipher, alist *pubkeys)
       cs->cryptoData->contentEncryptionAlgorithm = OBJ_nid2obj(NID_aes_128_cbc);
       ec = EVP_aes_128_cbc();
       break;
+#ifndef HAVE_OPENSSL_EXPORT_LIBRARY
    case CRYPTO_CIPHER_AES_192_CBC:
       /* AES 192 bit CBC */
       cs->cryptoData->contentEncryptionAlgorithm = OBJ_nid2obj(NID_aes_192_cbc);
@@ -1008,13 +1033,14 @@ CRYPTO_SESSION *crypto_session_new (crypto_cipher_t cipher, alist *pubkeys)
       cs->cryptoData->contentEncryptionAlgorithm = OBJ_nid2obj(NID_aes_256_cbc);
       ec = EVP_aes_256_cbc();
       break;
+#endif
    case CRYPTO_CIPHER_BLOWFISH_CBC:
       /* Blowfish CBC */
       cs->cryptoData->contentEncryptionAlgorithm = OBJ_nid2obj(NID_bf_cbc);
       ec = EVP_bf_cbc();
       break;
    default:
-      Emsg0(M_ERROR, 0, _("Unsupported cipher type specified\n"));
+      Jmsg0(NULL, M_ERROR, 0, _("Unsupported cipher type specified\n"));
       crypto_session_free(cs);
       return NULL;
    }
@@ -1030,12 +1056,7 @@ CRYPTO_SESSION *crypto_session_new (crypto_cipher_t cipher, alist *pubkeys)
 
    /* Generate an IV if possible */
    if ((iv_len = EVP_CIPHER_iv_length(ec))) {
-      iv = (unsigned char *) malloc(iv_len);
-      if (!iv) {
-         /* Malloc failure */
-         crypto_session_free(cs);
-         return NULL;
-      }
+      iv = (unsigned char *)malloc(iv_len);
 
       /* Generate random IV */
       if (RAND_bytes(iv, iv_len) <= 0) {
@@ -1083,12 +1104,7 @@ CRYPTO_SESSION *crypto_session_new (crypto_cipher_t cipher, alist *pubkeys)
       ri->keyEncryptionAlgorithm = OBJ_nid2obj(NID_rsaEncryption);
 
       /* Encrypt the session key */
-      ekey = (unsigned char *) malloc(EVP_PKEY_size(keypair->pubkey));
-      if (!ekey) {
-         RecipientInfo_free(ri);
-         crypto_session_free(cs);
-         return NULL;
-      }
+      ekey = (unsigned char *)malloc(EVP_PKEY_size(keypair->pubkey));
 
       if ((ekey_len = EVP_PKEY_encrypt(ekey, cs->session_key, cs->session_key_len, keypair->pubkey)) <= 0) {
          /* OpenSSL failure */
@@ -1163,10 +1179,7 @@ crypto_error_t crypto_session_decode(const uint8_t *data, uint32_t length, alist
       return CRYPTO_ERROR_NORECIPIENT;
    }
 
-   cs = (CRYPTO_SESSION *) malloc(sizeof(CRYPTO_SESSION));
-   if (!cs) {
-      return CRYPTO_ERROR_INTERNAL;
-   }
+   cs = (CRYPTO_SESSION *)malloc(sizeof(CRYPTO_SESSION));
 
    /* Initialize required fields */
    cs->session_key = NULL;
@@ -1215,7 +1228,7 @@ crypto_error_t crypto_session_decode(const uint8_t *data, uint32_t length, alist
 
             /* 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 = (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);
 
@@ -1243,7 +1256,7 @@ err:
 /*
  * Free memory associated with a crypto session object.
  */
-void crypto_session_free (CRYPTO_SESSION *cs)
+void crypto_session_free(CRYPTO_SESSION *cs)
 {
    if (cs->cryptoData) {
       CryptoData_free(cs->cryptoData);
@@ -1264,16 +1277,14 @@ CIPHER_CONTEXT *crypto_cipher_new(CRYPTO_SESSION *cs, bool encrypt, uint32_t *bl
    CIPHER_CONTEXT *cipher_ctx;
    const EVP_CIPHER *ec;
 
-   cipher_ctx = (CIPHER_CONTEXT *) malloc(sizeof(CIPHER_CONTEXT));
-   if (!cipher_ctx) {
-      return NULL;
-   }
+   cipher_ctx = (CIPHER_CONTEXT *)malloc(sizeof(CIPHER_CONTEXT));
 
    /*
     * 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));
+      Jmsg1(NULL, M_ERROR, 0, 
+         _("Unsupported contentEncryptionAlgorithm: %d\n"), OBJ_obj2nid(cs->cryptoData->contentEncryptionAlgorithm));
       free(cipher_ctx);
       return NULL;
    }
@@ -1376,7 +1387,9 @@ int init_crypto (void)
    int stat;
 
    if ((stat = openssl_init_threads()) != 0) {
-      Emsg1(M_ABORT, 0, _("Unable to init OpenSSL threading: ERR=%s\n"), strerror(stat));
+      berrno be;
+      Jmsg1(NULL, M_ABORT, 0, 
+        _("Unable to init OpenSSL threading: ERR=%s\n"), be.bstrerror(stat));
    }
 
    /* Load libssl and libcrypto human-readable error strings */
@@ -1389,7 +1402,7 @@ int init_crypto (void)
    OpenSSL_add_all_algorithms();
 
    if (!openssl_seed_prng()) {
-      Emsg0(M_ERROR_TERM, 0, _("Failed to seed OpenSSL PRNG\n"));
+      Jmsg0(NULL, M_ERROR_TERM, 0, _("Failed to seed OpenSSL PRNG\n"));
    }
 
    crypto_initialized = true;
@@ -1415,7 +1428,7 @@ int cleanup_crypto (void)
    }
 
    if (!openssl_save_prng()) {
-      Emsg0(M_ERROR, 0, _("Failed to save OpenSSL PRNG\n"));
+      Jmsg0(NULL, M_ERROR, 0, _("Failed to save OpenSSL PRNG\n"));
    }
 
    openssl_cleanup_threads();
@@ -1448,6 +1461,7 @@ int cleanup_crypto (void)
 /* Message Digest Structure */
 struct Digest {
    crypto_digest_t type;
+   JCR *jcr;
    union {
       SHA1Context sha1;
       MD5Context md5;
@@ -1456,6 +1470,7 @@ struct Digest {
 
 /* Dummy Signature Structure */
 struct Signature {
+   JCR *jcr;
 };
 
 DIGEST *crypto_digest_new(JCR *jcr, crypto_digest_t type)
@@ -1494,7 +1509,7 @@ bool crypto_digest_update(DIGEST *digest, const uint8_t *data, uint32_t length)
       if ((ret = SHA1Update(&digest->sha1, (const u_int8_t *) data, length)) == shaSuccess) {
          return true;
       } else {
-         Emsg1(M_ERROR, 0, _("SHA1Update() returned an error: %d\n"), ret);
+         Jmsg1(NULL, M_ERROR, 0, _("SHA1Update() returned an error: %d\n"), ret);
          return false;
       }
       break;
@@ -1543,13 +1558,16 @@ int cleanup_crypto (void) { return 0; }
 
 SIGNATURE *crypto_sign_new(JCR *jcr) { return NULL; }
 
-crypto_error_t crypto_sign_get_digest (SIGNATURE *sig, X509_KEYPAIR *keypair, DIGEST **digest) { return CRYPTO_ERROR_INTERNAL; }
+crypto_error_t crypto_sign_get_digest (SIGNATURE *sig, X509_KEYPAIR *keypair, 
+                                       crypto_digest_t &type, DIGEST **digest) 
+   { return CRYPTO_ERROR_INTERNAL; }
+
 crypto_error_t crypto_sign_verify (SIGNATURE *sig, X509_KEYPAIR *keypair, DIGEST *digest) { return CRYPTO_ERROR_INTERNAL; }
 
 int crypto_sign_add_signer (SIGNATURE *sig, DIGEST *digest, X509_KEYPAIR *keypair) { return false; }
 int crypto_sign_encode (SIGNATURE *sig, uint8_t *dest, uint32_t *length) { return false; }
 
-SIGNATURE *crypto_sign_decode (const uint8_t *sigData, uint32_t length) { return NULL; }
+SIGNATURE *crypto_sign_decode (JCR *jcr, const uint8_t *sigData, uint32_t length) { return NULL; }
 void crypto_sign_free (SIGNATURE *sig) { }
 
 
@@ -1588,7 +1606,8 @@ int crypto_default_pem_callback(char *buf, int size, const void *userdata)
  * Returns the ASCII name of the digest type.
  * Returns: ASCII name of digest type.
  */
-const char *crypto_digest_name (DIGEST *digest) {
+const char *crypto_digest_name(DIGEST *digest) 
+{
    switch (digest->type) {
    case CRYPTO_DIGEST_MD5:
       return "MD5";
@@ -1610,7 +1629,8 @@ const char *crypto_digest_name (DIGEST *digest) {
  * Given a stream type, returns the associated
  * crypto_digest_t value.
  */
-crypto_digest_t crypto_digest_stream_type (int stream) {
+crypto_digest_t crypto_digest_stream_type(int stream)
+{
    switch (stream) {
    case STREAM_MD5_DIGEST:
       return CRYPTO_DIGEST_MD5;