summaryrefslogtreecommitdiff
path: root/src/crypto/crypto.c
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2015-02-17 17:25:57 +0000
committer <>2015-03-17 16:26:24 +0000
commit780b92ada9afcf1d58085a83a0b9e6bc982203d1 (patch)
tree598f8b9fa431b228d29897e798de4ac0c1d3d970 /src/crypto/crypto.c
parent7a2660ba9cc2dc03a69ddfcfd95369395cc87444 (diff)
downloadberkeleydb-master.tar.gz
Imported from /home/lorry/working-area/delta_berkeleydb/db-6.1.23.tar.gz.HEADdb-6.1.23master
Diffstat (limited to 'src/crypto/crypto.c')
-rw-r--r--src/crypto/crypto.c77
1 files changed, 65 insertions, 12 deletions
diff --git a/src/crypto/crypto.c b/src/crypto/crypto.c
index b731496f..ba115dd3 100644
--- a/src/crypto/crypto.c
+++ b/src/crypto/crypto.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015 Oracle and/or its affiliates. All rights reserved.
*
* Some parts of this code originally written by Adam Stubblefield
* -- astubble@rice.edu
@@ -15,6 +15,8 @@
#include "dbinc/db_page.h"
#include "dbinc/crypto.h"
+static void randomize __P((ENV *, void *, size_t));
+
/*
* __crypto_region_init --
* Initialize crypto.
@@ -110,7 +112,7 @@ __crypto_region_init(env)
* existing one, we are done with the passwd in the env. We smash
* N-1 bytes so that we don't overwrite the nul.
*/
- memset(dbenv->passwd, 0xff, dbenv->passwd_len-1);
+ randomize(env, dbenv->passwd, dbenv->passwd_len - 1);
__os_free(env, dbenv->passwd);
dbenv->passwd = NULL;
dbenv->passwd_len = 0;
@@ -135,9 +137,10 @@ __crypto_env_close(env)
dbenv = env->dbenv;
if (dbenv->passwd != NULL) {
- memset(dbenv->passwd, 0xff, dbenv->passwd_len-1);
+ randomize(env, dbenv->passwd, dbenv->passwd_len - 1);
__os_free(env, dbenv->passwd);
dbenv->passwd = NULL;
+ dbenv->passwd_len = 0;
}
if (!CRYPTO_ON(env))
@@ -225,7 +228,8 @@ __crypto_algsetup(env, db_cipher, alg, do_init)
/*
* __crypto_decrypt_meta --
- * Perform decryption on a metapage if needed.
+ * Perform decryption on a possible metadata page, if needed. This is used
+ * to help decide whether this is a real DB. Don't trust random data.
*
* PUBLIC: int __crypto_decrypt_meta __P((ENV *, DB *, u_int8_t *, int));
*/
@@ -241,6 +245,7 @@ __crypto_decrypt_meta(env, dbp, mbuf, do_metachk)
DB_CIPHER *db_cipher;
size_t pg_off;
int ret;
+ unsigned added_flags;
u_int8_t *iv;
/*
@@ -293,6 +298,7 @@ __crypto_decrypt_meta(env, dbp, mbuf, do_metachk)
*/
if (meta->encrypt_alg != 0) {
db_cipher = env->crypto_handle;
+ added_flags = 0;
if (!F_ISSET(dbp, DB_AM_ENCRYPT)) {
if (!CRYPTO_ON(env)) {
__db_errx(env, DB_STR("0178",
@@ -300,12 +306,14 @@ __crypto_decrypt_meta(env, dbp, mbuf, do_metachk)
return (EINVAL);
}
/*
- * User has a correct, secure env, but has encountered
- * a database in that env that is secure, but user
- * didn't dbp->set_flags. Since it is existing, use
- * encryption if it is that way already.
+ * User has a correct, secure env and has encountered
+ * a database in that env that APPEARS TO BE secure, but
+ * user didn't set the encryption flags. Since the db
+ * already exists, turn encryption on. Remember what was
+ * set, so the flags can restored if it doesn't decrypt.
*/
- F_SET(dbp, DB_AM_ENCRYPT|DB_AM_CHKSUM);
+ added_flags = DB_AM_ENCRYPT | DB_AM_CHKSUM;
+ F_SET(dbp, added_flags);
}
/*
* This was checked in set_flags when DB_AM_ENCRYPT was set.
@@ -316,6 +324,7 @@ __crypto_decrypt_meta(env, dbp, mbuf, do_metachk)
meta->encrypt_alg != db_cipher->alg) {
__db_errx(env, DB_STR("0179",
"Database encrypted using a different algorithm"));
+ F_CLR(dbp, added_flags);
return (EINVAL);
}
DB_ASSERT(env, F_ISSET(dbp, DB_AM_CHKSUM));
@@ -334,12 +343,14 @@ alg_retry:
if (!F_ISSET(db_cipher, CIPHER_ANY)) {
if (do_metachk && (ret = db_cipher->decrypt(env,
db_cipher->data, iv, mbuf + pg_off,
- DBMETASIZE - pg_off)))
+ DBMETASIZE - pg_off))) {
+ F_CLR(dbp, added_flags);
return (ret);
- if (((BTMETA *)meta)->crypto_magic !=
- meta->magic) {
+ }
+ if (((BTMETA *)meta)->crypto_magic != meta->magic) {
__db_errx(env, DB_STR("0180",
"Invalid password"));
+ F_CLR(dbp, added_flags);
return (EINVAL);
}
/*
@@ -409,3 +420,45 @@ __crypto_set_passwd(env_src, env_dest)
sh_passwd = R_ADDR(infop, cipher->passwd);
return (__env_set_encrypt(env_dest->dbenv, sh_passwd, DB_ENCRYPT_AES));
}
+
+/*
+ * randomize
+ *
+ */
+static void
+randomize(env, base, size)
+ ENV *env;
+ void *base;
+ size_t size;
+{
+ size_t i, copysize;
+ u_int8_t last, *p;
+ u_int32_t value;
+
+ last = ((u_int8_t *)base)[size];
+ for (i = 0, p = base; i < size; i += copysize, p += copysize) {
+ value = __os_random();
+ if ((copysize = (size - i)) > sizeof(int32_t))
+ copysize = sizeof(int32_t);
+ switch (copysize)
+ {
+ default:
+ memmove(p, &value, sizeof(int32_t));
+ break;
+ case 3:
+ p[2] = (u_int8_t)(value >> 16);
+ /* FALLTHROUGH */
+ case 2:
+ p[1] = (u_int8_t)(value >> 8);
+ /* FALLTHROUGH */
+ case 1:
+ p[0] = (u_int8_t)(value);
+ break;
+ case 0:
+ DB_ASSERT(env, "randomize size 0?");
+ break;
+ }
+
+ }
+ DB_ASSERT(env, last == *p);
+}