#include "dsdb/samdb/samdb.h"
#include "dsdb/samdb/ldb_modules/util.h"
-/* Build either with GnuTLS crypto or Samba crypto. */
-#ifdef HAVE_GNUTLS_AEAD
- #define BUILD_WITH_GNUTLS_AEAD
-#else /* !HAVE_GNUTLS_AEAD */
- #define BUILD_WITH_SAMBA_AES_GCM
-#endif /* HAVE_GNUTLS_AEAD */
-
-#ifdef BUILD_WITH_GNUTLS_AEAD
- #include <gnutls/gnutls.h>
- #include <gnutls/crypto.h>
-#endif /* BUILD_WITH_GNUTLS_AEAD */
-
-#ifdef BUILD_WITH_SAMBA_AES_GCM
- #include "lib/crypto/aes.h"
- #include "lib/crypto/aes_gcm_128.h"
-#endif /* BUILD_WITH_SAMBA_AES_GCM */
+#include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
static const char * const secret_attributes[] = {DSDB_SECRET_ATTRIBUTES};
static const size_t num_secret_attributes = ARRAY_SIZE(secret_attributes);
* Encryption keys for secret attributes
*/
DATA_BLOB keys[NUMBER_OF_KEYS];
-#ifdef BUILD_WITH_GNUTLS_AEAD
/*
* The gnutls algorithm used to encrypt attributes
*/
int encryption_algorithm;
-#endif /* BUILD_WITH_GNUTLS_AEAD */
};
/*
data->keys[0] = key;
data->encrypt_secrets = true;
-#ifdef BUILD_WITH_GNUTLS_AEAD
data->encryption_algorithm = GNUTLS_CIPHER_AES_128_GCM;
-#endif
TALLOC_FREE(frame);
return LDB_SUCCESS;
*
* @return Size rounded up to the nearest multiple of block_size
*/
-#ifdef BUILD_WITH_GNUTLS_AEAD
static size_t round_to_block_size(size_t block_size, size_t size)
{
if ((size % block_size) == 0) {
return ((int)(size/block_size) + 1) * block_size;
}
}
-#endif /* BUILD_WITH_GNUTLS_AEAD */
/*
* @brief Create an new EncryptedSecret owned by the supplied talloc context.
return pt;
}
-#ifdef BUILD_WITH_SAMBA_AES_GCM
-/*
- * @brief Encrypt an ldb value using an aead algorithm.
- *
- * This function uses the samba internal implementation to perform the encryption. However
- * the encrypted data and tag are stored in a manner compatible with gnutls,
- * so the gnutls aead functions can be used to decrypt and verify the data.
- *
- * @param err Pointer to an error code, set to:
- * LDB_SUCESS If the value was successfully encrypted
- * LDB_ERR_OPERATIONS_ERROR If there was an error.
- *
- * @param ctx Talloc memory context the will own the memory allocated
- * @param ldb ldb context, to allow logging.
- * @param val The ldb value to encrypt, not altered or freed
- * @param data The context data for this module.
- *
- * @return The encrypted ldb_val, or data_blob_null if there was an error.
- */
-static struct ldb_val samba_encrypt_aead(int *err,
- TALLOC_CTX *ctx,
- struct ldb_context *ldb,
- const struct ldb_val val,
- const struct es_data *data)
-{
- struct aes_gcm_128_context cctx;
- struct EncryptedSecret *es = NULL;
- DATA_BLOB pt = data_blob_null;
- struct ldb_val enc = data_blob_null;
- DATA_BLOB key_blob = data_blob_null;
- int rc;
- TALLOC_CTX *frame = talloc_stackframe();
-
- es = makeEncryptedSecret(ldb, frame);
- if (es == NULL) {
- goto error_exit;
- }
-
- pt = makePlainText(frame, ldb, val);
- if (pt.length == 0) {
- goto error_exit;
- }
-
- /*
- * Set the encryption key
- */
- key_blob = get_key(data);
- if (key_blob.length != AES_BLOCK_SIZE) {
- ldb_asprintf_errstring(ldb,
- "Invalid EncryptedSecrets key size, "
- "expected %u bytes and is %zu bytes\n",
- AES_BLOCK_SIZE,
- key_blob.length);
- goto error_exit;
- }
-
- /*
- * Set the initialisation vector
- */
- {
- uint8_t *iv = talloc_zero_size(frame, AES_GCM_128_IV_SIZE);
- if (iv == NULL) {
- ldb_set_errstring(ldb,
- "Out of memory allocating iv\n");
- goto error_exit;
- }
-
- generate_nonce_buffer(iv, AES_GCM_128_IV_SIZE);
-
- es->iv.length = AES_GCM_128_IV_SIZE;
- es->iv.data = iv;
- }
-
- /*
- * Encrypt the value, and append the GCM digest to the encrypted
- * data so that it can be decrypted and validated by the
- * gnutls aead decryption routines.
- */
- {
- uint8_t *ct = talloc_zero_size(frame, pt.length + AES_BLOCK_SIZE);
- if (ct == NULL) {
- ldb_oom(ldb);
- goto error_exit;
- }
-
- memcpy(ct, pt.data, pt.length);
- es->encrypted.length = pt.length + AES_BLOCK_SIZE;
- es->encrypted.data = ct;
- }
-
- aes_gcm_128_init(&cctx, key_blob.data, es->iv.data);
- aes_gcm_128_updateA(&cctx,
- (uint8_t *)&es->header,
- sizeof(struct EncryptedSecretHeader));
- aes_gcm_128_crypt(&cctx, es->encrypted.data, pt.length);
- aes_gcm_128_updateC(&cctx, es->encrypted.data, pt.length);
- aes_gcm_128_digest(&cctx, &es->encrypted.data[pt.length]);
-
- rc = ndr_push_struct_blob(&enc,
- ctx,
- es,
- (ndr_push_flags_fn_t)
- ndr_push_EncryptedSecret);
- if (!NDR_ERR_CODE_IS_SUCCESS(rc)) {
- ldb_set_errstring(ldb,
- "Unable to ndr push EncryptedSecret\n");
- goto error_exit;
- }
- TALLOC_FREE(frame);
- return enc;
-
-error_exit:
- *err = LDB_ERR_OPERATIONS_ERROR;
- TALLOC_FREE(frame);
- return data_blob_null;
-}
-
-/*
- * @brief Decrypt data encrypted using an aead algorithm.
- *
- * Decrypt the data in ed and insert it into ev. The data was encrypted
- * with the samba aes gcm implementation.
- *
- * @param err Pointer to an error code, set to:
- * LDB_SUCESS If the value was successfully decrypted
- * LDB_ERR_OPERATIONS_ERROR If there was an error.
- *
- * @param ctx Talloc memory context that will own the memory allocated
- * @param ldb ldb context, to allow logging.
- * @param ev The value to be updated with the decrypted data.
- * @param ed The data to decrypt.
- * @param data The context data for this module.
- *
- * @return ev is updated with the unencrypted data.
- */
-static void samba_decrypt_aead(int *err,
- TALLOC_CTX *ctx,
- struct ldb_context *ldb,
- struct EncryptedSecret *es,
- struct PlaintextSecret *ps,
- const struct es_data *data)
-{
- struct aes_gcm_128_context cctx;
- DATA_BLOB pt = data_blob_null;
- DATA_BLOB key_blob = data_blob_null;
- uint8_t sig[AES_BLOCK_SIZE] = {0, };
- int rc;
- int cmp;
- TALLOC_CTX *frame = talloc_stackframe();
-
- /*
- * Set the encryption key
- */
- key_blob = get_key(data);
- if (key_blob.length != AES_BLOCK_SIZE) {
- ldb_asprintf_errstring(ldb,
- "Invalid EncryptedSecrets key size, "
- "expected %u bytes and is %zu bytes\n",
- AES_BLOCK_SIZE,
- key_blob.length);
- goto error_exit;
- }
-
- if (es->iv.length < AES_GCM_128_IV_SIZE) {
- ldb_asprintf_errstring(ldb,
- "Invalid EncryptedSecrets iv size, "
- "expected %u bytes and is %zu bytes\n",
- AES_GCM_128_IV_SIZE,
- es->iv.length);
- goto error_exit;
- }
-
- if (es->encrypted.length < AES_BLOCK_SIZE) {
- ldb_asprintf_errstring(ldb,
- "Invalid EncryptedData size, "
- "expected %u bytes and is %zu bytes\n",
- AES_BLOCK_SIZE,
- es->encrypted.length);
- goto error_exit;
- }
-
- pt.length = es->encrypted.length - AES_BLOCK_SIZE;
- pt.data = talloc_zero_size(ctx, pt.length);
- if (pt.data == NULL) {
- ldb_set_errstring(ldb,
- "Out of memory allocating space for "
- "plain text\n");
- goto error_exit;
- }
- memcpy(pt.data, es->encrypted.data, pt.length);
-
- aes_gcm_128_init(&cctx, key_blob.data, es->iv.data);
- aes_gcm_128_updateA(&cctx,
- (uint8_t *)&es->header,
- sizeof(struct EncryptedSecretHeader));
- aes_gcm_128_updateC(&cctx, pt.data, pt.length);
- aes_gcm_128_crypt(&cctx, pt.data, pt.length);
- aes_gcm_128_digest(&cctx, sig);
-
- /*
- * Check the authentication tag
- */
- cmp = memcmp(&es->encrypted.data[pt.length], sig, AES_BLOCK_SIZE);
- if (cmp != 0) {
- ldb_set_errstring(ldb,
- "Tag does not match, "
- "data corrupted or altered\n");
- goto error_exit;
- }
-
- rc = ndr_pull_struct_blob(&pt,
- ctx,
- ps,
- (ndr_pull_flags_fn_t)
- ndr_pull_PlaintextSecret);
- if(!NDR_ERR_CODE_IS_SUCCESS(rc)) {
- ldb_asprintf_errstring(ldb,
- "Error(%d) unpacking decrypted data, "
- "data possibly corrupted or altered\n",
- rc);
- goto error_exit;
- }
- TALLOC_FREE(frame);
- return;
-
-error_exit:
- *err = LDB_ERR_OPERATIONS_ERROR;
- TALLOC_FREE(frame);
- return;
-}
-#endif /* BUILD_WITH_SAMBA_AES_GCM */
-
-#ifdef BUILD_WITH_GNUTLS_AEAD
/*
* Helper function converts a data blob to a gnutls_datum_t.
*err = LDB_ERR_OPERATIONS_ERROR;
return;
}
-#endif /* BUILD_WITH_GNUTLS_AEAD */
/*
* @brief Encrypt an attribute value using the default encryption algorithm.
const struct ldb_val val,
const struct es_data *data)
{
-#ifdef BUILD_WITH_GNUTLS_AEAD
return gnutls_encrypt_aead(err, ctx, ldb, val, data);
-#elif defined BUILD_WITH_SAMBA_AES_GCM
- return samba_encrypt_aead(err, ctx, ldb, val, data);
-#endif
}
/*
*err = LDB_ERR_OPERATIONS_ERROR;
return data_blob_null;
}
-#ifdef BUILD_WITH_GNUTLS_AEAD
gnutls_decrypt_aead(err, frame, ldb, &es, &ps, data);
-#elif defined BUILD_WITH_SAMBA_AES_GCM
- samba_decrypt_aead(err, frame, ldb, &es, &ps, data);
-#endif
if (*err != LDB_SUCCESS) {
TALLOC_FREE(frame);