00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "db_config.h"
00014
00015 #ifndef NO_SYSTEM_INCLUDES
00016 #include <string.h>
00017 #endif
00018
00019 #include "db_int.h"
00020 #include "dbinc/db_page.h"
00021 #include "dbinc/crypto.h"
00022
00023
00024
00025
00026
00027 int
00028 __crypto_region_init(dbenv)
00029 DB_ENV *dbenv;
00030 {
00031 REGENV *renv;
00032 REGINFO *infop;
00033 CIPHER *cipher;
00034 DB_CIPHER *db_cipher;
00035 char *sh_passwd;
00036 int ret;
00037
00038 db_cipher = dbenv->crypto_handle;
00039
00040 ret = 0;
00041 infop = dbenv->reginfo;
00042 renv = infop->primary;
00043 if (renv->cipher_off == INVALID_ROFF) {
00044 if (!CRYPTO_ON(dbenv))
00045 return (0);
00046 if (!F_ISSET(infop, REGION_CREATE)) {
00047 __db_err(dbenv,
00048 "Joining non-encrypted environment with encryption key");
00049 return (EINVAL);
00050 }
00051 if (F_ISSET(db_cipher, CIPHER_ANY)) {
00052 __db_err(dbenv, "Encryption algorithm not supplied");
00053 return (EINVAL);
00054 }
00055
00056
00057
00058
00059
00060 if ((ret =
00061 __db_shalloc(infop, sizeof(CIPHER), 0, &cipher)) != 0)
00062 return (ret);
00063 memset(cipher, 0, sizeof(*cipher));
00064 if ((ret = __db_shalloc(
00065 infop, dbenv->passwd_len, 0, &sh_passwd)) != 0) {
00066 __db_shalloc_free(infop, cipher);
00067 return (ret);
00068 }
00069 memset(sh_passwd, 0, dbenv->passwd_len);
00070 cipher->passwd = R_OFFSET(infop, sh_passwd);
00071 cipher->passwd_len = dbenv->passwd_len;
00072 cipher->flags = db_cipher->alg;
00073 memcpy(sh_passwd, dbenv->passwd, cipher->passwd_len);
00074 renv->cipher_off = R_OFFSET(infop, cipher);
00075 } else {
00076 if (!CRYPTO_ON(dbenv)) {
00077 __db_err(dbenv,
00078 "Encrypted environment: no encryption key supplied");
00079 return (EINVAL);
00080 }
00081 cipher = R_ADDR(infop, renv->cipher_off);
00082 sh_passwd = R_ADDR(infop, cipher->passwd);
00083 if ((cipher->passwd_len != dbenv->passwd_len) ||
00084 memcmp(dbenv->passwd, sh_passwd, cipher->passwd_len) != 0) {
00085 __db_err(dbenv, "Invalid password");
00086 return (EPERM);
00087 }
00088 if (!F_ISSET(db_cipher, CIPHER_ANY) &&
00089 db_cipher->alg != cipher->flags) {
00090 __db_err(dbenv,
00091 "Environment encrypted using a different algorithm");
00092 return (EINVAL);
00093 }
00094 if (F_ISSET(db_cipher, CIPHER_ANY))
00095
00096
00097
00098
00099
00100 if ((ret = __crypto_algsetup(dbenv, db_cipher,
00101 cipher->flags, 0)) != 0)
00102 return (ret);
00103 }
00104 ret = db_cipher->init(dbenv, db_cipher);
00105
00106
00107
00108
00109
00110
00111 memset(dbenv->passwd, 0xff, dbenv->passwd_len-1);
00112 __os_free(dbenv, dbenv->passwd);
00113 dbenv->passwd = NULL;
00114 dbenv->passwd_len = 0;
00115
00116 return (ret);
00117 }
00118
00119
00120
00121
00122
00123
00124
00125 int
00126 __crypto_dbenv_close(dbenv)
00127 DB_ENV *dbenv;
00128 {
00129 DB_CIPHER *db_cipher;
00130 int ret;
00131
00132 ret = 0;
00133 db_cipher = dbenv->crypto_handle;
00134 if (dbenv->passwd != NULL) {
00135 memset(dbenv->passwd, 0xff, dbenv->passwd_len-1);
00136 __os_free(dbenv, dbenv->passwd);
00137 dbenv->passwd = NULL;
00138 }
00139 if (!CRYPTO_ON(dbenv))
00140 return (0);
00141 if (!F_ISSET(db_cipher, CIPHER_ANY))
00142 ret = db_cipher->close(dbenv, db_cipher->data);
00143 __os_free(dbenv, db_cipher);
00144 return (ret);
00145 }
00146
00147
00148
00149
00150
00151
00152
00153 int
00154 __crypto_region_destroy(dbenv)
00155 DB_ENV *dbenv;
00156 {
00157 CIPHER *cipher;
00158 REGENV *renv;
00159 REGINFO *infop;
00160
00161 infop = dbenv->reginfo;
00162 renv = infop->primary;
00163 if (renv->cipher_off != INVALID_ROFF) {
00164 cipher = R_ADDR(infop, renv->cipher_off);
00165 __db_shalloc_free(infop, R_ADDR(infop, cipher->passwd));
00166 __db_shalloc_free(infop, cipher);
00167 }
00168 return (0);
00169 }
00170
00171
00172
00173
00174
00175
00176
00177
00178 int
00179 __crypto_algsetup(dbenv, db_cipher, alg, do_init)
00180 DB_ENV *dbenv;
00181 DB_CIPHER *db_cipher;
00182 u_int32_t alg;
00183 int do_init;
00184 {
00185 int ret;
00186
00187 ret = 0;
00188 if (!CRYPTO_ON(dbenv)) {
00189 __db_err(dbenv, "No cipher structure given");
00190 return (EINVAL);
00191 }
00192 F_CLR(db_cipher, CIPHER_ANY);
00193 switch (alg) {
00194 case CIPHER_AES:
00195 db_cipher->alg = CIPHER_AES;
00196 ret = __aes_setup(dbenv, db_cipher);
00197 break;
00198 default:
00199 __db_panic(dbenv, EINVAL);
00200
00201 }
00202 if (do_init)
00203 ret = db_cipher->init(dbenv, db_cipher);
00204 return (ret);
00205 }
00206
00207
00208
00209
00210
00211
00212
00213 int
00214 __crypto_decrypt_meta(dbenv, dbp, mbuf, do_metachk)
00215 DB_ENV *dbenv;
00216 DB *dbp;
00217 u_int8_t *mbuf;
00218 int do_metachk;
00219 {
00220 DB_CIPHER *db_cipher;
00221 DB dummydb;
00222 DBMETA *meta;
00223 size_t pg_off;
00224 int ret;
00225 u_int8_t *iv;
00226
00227
00228
00229
00230
00231
00232
00233 if (dbp == NULL) {
00234 memset(&dummydb, 0, sizeof(DB));
00235 dbp = &dummydb;
00236 }
00237
00238 ret = 0;
00239 meta = (DBMETA *)mbuf;
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 if (meta->magic == DB_HASHMAGIC && meta->version <= 5)
00259 return (0);
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276 if (meta->encrypt_alg != 0) {
00277 db_cipher = (DB_CIPHER *)dbenv->crypto_handle;
00278 if (!F_ISSET(dbp, DB_AM_ENCRYPT)) {
00279 if (!CRYPTO_ON(dbenv)) {
00280 __db_err(dbenv,
00281 "Encrypted database: no encryption flag specified");
00282 return (EINVAL);
00283 }
00284
00285
00286
00287
00288
00289
00290 F_SET(dbp, DB_AM_ENCRYPT|DB_AM_CHKSUM);
00291 }
00292
00293
00294
00295
00296 DB_ASSERT(CRYPTO_ON(dbenv));
00297 if (!F_ISSET(db_cipher, CIPHER_ANY) &&
00298 meta->encrypt_alg != db_cipher->alg) {
00299 __db_err(dbenv,
00300 "Database encrypted using a different algorithm");
00301 return (EINVAL);
00302 }
00303 DB_ASSERT(F_ISSET(dbp, DB_AM_CHKSUM));
00304 iv = ((BTMETA *)mbuf)->iv;
00305
00306
00307
00308
00309
00310 pg_off = P_OVERHEAD(dbp);
00311 alg_retry:
00312
00313
00314
00315
00316 if (!F_ISSET(db_cipher, CIPHER_ANY)) {
00317 if (do_metachk && (ret = db_cipher->decrypt(dbenv,
00318 db_cipher->data, iv, mbuf + pg_off,
00319 DBMETASIZE - pg_off)))
00320 return (ret);
00321 if (((BTMETA *)meta)->crypto_magic !=
00322 meta->magic) {
00323 __db_err(dbenv, "Invalid password");
00324 return (EINVAL);
00325 }
00326
00327
00328
00329
00330
00331
00332
00333 return (0);
00334 }
00335
00336
00337
00338 ret = __crypto_algsetup(dbenv, db_cipher, meta->encrypt_alg, 1);
00339 goto alg_retry;
00340 } else if (F_ISSET(dbp, DB_AM_ENCRYPT)) {
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 __db_err(dbenv,
00362 "Unencrypted database with a supplied encryption key");
00363 return (EINVAL);
00364 }
00365 return (ret);
00366 }
00367
00368
00369
00370
00371
00372
00373
00374
00375 int
00376 __crypto_set_passwd(dbenv_src, dbenv_dest)
00377 DB_ENV *dbenv_src, *dbenv_dest;
00378 {
00379 CIPHER *cipher;
00380 REGENV *renv;
00381 REGINFO *infop;
00382 char *sh_passwd;
00383 int ret;
00384
00385 ret = 0;
00386 infop = dbenv_src->reginfo;
00387 renv = infop->primary;
00388
00389 DB_ASSERT(CRYPTO_ON(dbenv_src));
00390
00391 cipher = R_ADDR(infop, renv->cipher_off);
00392 sh_passwd = R_ADDR(infop, cipher->passwd);
00393 return (__env_set_encrypt(dbenv_dest, sh_passwd, DB_ENCRYPT_AES));
00394 }