00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include "db_config.h"
00043
00044 #ifndef NO_SYSTEM_INCLUDES
00045 #include <sys/types.h>
00046
00047 #include <string.h>
00048 #endif
00049
00050 #include "db_int.h"
00051 #include "dbinc/crypto.h"
00052 #include "dbinc/hmac.h"
00053 #include "dbinc/db_page.h"
00054 #include "dbinc/db_swap.h"
00055 #include "dbinc/btree.h"
00056 #include "dbinc/hash.h"
00057 #include "dbinc/log.h"
00058 #include "dbinc/qam.h"
00059
00060
00061
00062
00063
00064
00065
00066 int
00067 __db_pgin(dbenv, pg, pp, cookie)
00068 DB_ENV *dbenv;
00069 db_pgno_t pg;
00070 void *pp;
00071 DBT *cookie;
00072 {
00073 DB dummydb, *dbp;
00074 DB_PGINFO *pginfo;
00075 DB_CIPHER *db_cipher;
00076 DB_LSN not_used;
00077 PAGE *pagep;
00078 size_t pg_off, pg_len, sum_len;
00079 int is_hmac, ret;
00080 u_int8_t *chksum, *iv;
00081
00082 pginfo = (DB_PGINFO *)cookie->data;
00083 pagep = (PAGE *)pp;
00084
00085 ret = is_hmac = 0;
00086 chksum = iv = NULL;
00087 memset(&dummydb, 0, sizeof(DB));
00088 dbp = &dummydb;
00089 dummydb.flags = pginfo->flags;
00090 db_cipher = (DB_CIPHER *)dbenv->crypto_handle;
00091 switch (pagep->type) {
00092 case P_HASHMETA:
00093 case P_BTREEMETA:
00094 case P_QAMMETA:
00095
00096
00097
00098
00099 if (FLD_ISSET(((DBMETA *)pp)->metaflags, DBMETA_CHKSUM))
00100 F_SET(dbp, DB_AM_CHKSUM);
00101 else
00102 F_CLR(dbp, DB_AM_CHKSUM);
00103 if (((DBMETA *)pp)->encrypt_alg != 0 ||
00104 F_ISSET(dbp, DB_AM_ENCRYPT))
00105 is_hmac = 1;
00106
00107
00108
00109
00110
00111
00112 chksum = ((BTMETA *)pp)->chksum;
00113 sum_len = DBMETASIZE;
00114 break;
00115 case P_INVALID:
00116
00117
00118
00119
00120
00121 if (IS_ZERO_LSN(LSN(pagep)) && pagep->pgno == PGNO_INVALID) {
00122 sum_len = 0;
00123 break;
00124 }
00125
00126 default:
00127 chksum = P_CHKSUM(dbp, pagep);
00128 sum_len = pginfo->db_pagesize;
00129
00130
00131
00132
00133 is_hmac = CRYPTO_ON(dbenv) ? 1 : 0;
00134 break;
00135 }
00136
00137
00138
00139
00140
00141
00142 if (F_ISSET(dbp, DB_AM_CHKSUM) && sum_len != 0) {
00143 if (F_ISSET(dbp, DB_AM_SWAP) && is_hmac == 0)
00144 P_32_SWAP(chksum);
00145 switch (ret = __db_check_chksum(
00146 dbenv, db_cipher, chksum, pp, sum_len, is_hmac)) {
00147 case 0:
00148 break;
00149 case -1:
00150 if (DBENV_LOGGING(dbenv))
00151 (void)__db_cksum_log(
00152 dbenv, NULL, ¬_used, DB_FLUSH);
00153 __db_err(dbenv,
00154 "checksum error: page %lu: catastrophic recovery required",
00155 (u_long)pg);
00156 return (__db_panic(dbenv, DB_RUNRECOVERY));
00157 default:
00158 return (ret);
00159 }
00160 }
00161 if (F_ISSET(dbp, DB_AM_ENCRYPT)) {
00162 DB_ASSERT(db_cipher != NULL);
00163 DB_ASSERT(F_ISSET(dbp, DB_AM_CHKSUM));
00164
00165 pg_off = P_OVERHEAD(dbp);
00166 DB_ASSERT(db_cipher->adj_size(pg_off) == 0);
00167
00168 switch (pagep->type) {
00169 case P_HASHMETA:
00170 case P_BTREEMETA:
00171 case P_QAMMETA:
00172
00173
00174
00175
00176
00177
00178 iv = ((BTMETA *)pp)->iv;
00179 pg_len = DBMETASIZE;
00180 break;
00181 case P_INVALID:
00182 if (IS_ZERO_LSN(LSN(pagep)) &&
00183 pagep->pgno == PGNO_INVALID) {
00184 pg_len = 0;
00185 break;
00186 }
00187
00188 default:
00189 iv = P_IV(dbp, pagep);
00190 pg_len = pginfo->db_pagesize;
00191 break;
00192 }
00193 if (pg_len != 0 && (ret = db_cipher->decrypt(dbenv,
00194 db_cipher->data, iv, ((u_int8_t *)pagep) + pg_off,
00195 pg_len - pg_off)) != 0)
00196 return (ret);
00197 }
00198 switch (pagep->type) {
00199 case P_INVALID:
00200 if (pginfo->type == DB_QUEUE)
00201 return (__qam_pgin_out(dbenv, pg, pp, cookie));
00202 else
00203 return (__ham_pgin(dbenv, dbp, pg, pp, cookie));
00204 case P_HASH:
00205 case P_HASHMETA:
00206 return (__ham_pgin(dbenv, dbp, pg, pp, cookie));
00207 case P_BTREEMETA:
00208 case P_IBTREE:
00209 case P_IRECNO:
00210 case P_LBTREE:
00211 case P_LDUP:
00212 case P_LRECNO:
00213 case P_OVERFLOW:
00214 return (__bam_pgin(dbenv, dbp, pg, pp, cookie));
00215 case P_QAMMETA:
00216 case P_QAMDATA:
00217 return (__qam_pgin_out(dbenv, pg, pp, cookie));
00218 default:
00219 break;
00220 }
00221 return (__db_pgfmt(dbenv, pg));
00222 }
00223
00224
00225
00226
00227
00228
00229
00230 int
00231 __db_pgout(dbenv, pg, pp, cookie)
00232 DB_ENV *dbenv;
00233 db_pgno_t pg;
00234 void *pp;
00235 DBT *cookie;
00236 {
00237 DB dummydb, *dbp;
00238 DB_CIPHER *db_cipher;
00239 DB_PGINFO *pginfo;
00240 PAGE *pagep;
00241 size_t pg_off, pg_len, sum_len;
00242 int ret;
00243 u_int8_t *chksum, *iv, *key;
00244
00245 pginfo = (DB_PGINFO *)cookie->data;
00246 pagep = (PAGE *)pp;
00247
00248 chksum = iv = key = NULL;
00249 memset(&dummydb, 0, sizeof(DB));
00250 dbp = &dummydb;
00251 dummydb.flags = pginfo->flags;
00252 ret = 0;
00253 switch (pagep->type) {
00254 case P_INVALID:
00255 if (pginfo->type == DB_QUEUE)
00256 ret = __qam_pgin_out(dbenv, pg, pp, cookie);
00257 else
00258 ret = __ham_pgout(dbenv, dbp, pg, pp, cookie);
00259 break;
00260 case P_HASH:
00261 case P_HASHMETA:
00262 ret = __ham_pgout(dbenv, dbp, pg, pp, cookie);
00263 break;
00264 case P_BTREEMETA:
00265 case P_IBTREE:
00266 case P_IRECNO:
00267 case P_LBTREE:
00268 case P_LDUP:
00269 case P_LRECNO:
00270 case P_OVERFLOW:
00271 ret = __bam_pgout(dbenv, dbp, pg, pp, cookie);
00272 break;
00273 case P_QAMMETA:
00274 case P_QAMDATA:
00275 ret = __qam_pgin_out(dbenv, pg, pp, cookie);
00276 break;
00277 default:
00278 return (__db_pgfmt(dbenv, pg));
00279 }
00280 if (ret)
00281 return (ret);
00282
00283 db_cipher = (DB_CIPHER *)dbenv->crypto_handle;
00284 if (F_ISSET(dbp, DB_AM_ENCRYPT)) {
00285
00286 DB_ASSERT(db_cipher != NULL);
00287 DB_ASSERT(F_ISSET(dbp, DB_AM_CHKSUM));
00288
00289 pg_off = P_OVERHEAD(dbp);
00290 DB_ASSERT(db_cipher->adj_size(pg_off) == 0);
00291
00292 key = db_cipher->mac_key;
00293
00294 switch (pagep->type) {
00295 case P_HASHMETA:
00296 case P_BTREEMETA:
00297 case P_QAMMETA:
00298
00299
00300
00301
00302
00303
00304 iv = ((BTMETA *)pp)->iv;
00305 pg_len = DBMETASIZE;
00306 break;
00307 default:
00308 iv = P_IV(dbp, pagep);
00309 pg_len = pginfo->db_pagesize;
00310 break;
00311 }
00312 if ((ret = db_cipher->encrypt(dbenv, db_cipher->data,
00313 iv, ((u_int8_t *)pagep) + pg_off, pg_len - pg_off)) != 0)
00314 return (ret);
00315 }
00316 if (F_ISSET(dbp, DB_AM_CHKSUM)) {
00317 switch (pagep->type) {
00318 case P_HASHMETA:
00319 case P_BTREEMETA:
00320 case P_QAMMETA:
00321
00322
00323
00324
00325
00326
00327 chksum = ((BTMETA *)pp)->chksum;
00328 sum_len = DBMETASIZE;
00329 break;
00330 default:
00331 chksum = P_CHKSUM(dbp, pagep);
00332 sum_len = pginfo->db_pagesize;
00333 break;
00334 }
00335 __db_chksum(pp, sum_len, key, chksum);
00336 if (F_ISSET(dbp, DB_AM_SWAP) && !F_ISSET(dbp, DB_AM_ENCRYPT))
00337 P_32_SWAP(chksum);
00338 }
00339 return (0);
00340 }
00341
00342
00343
00344
00345
00346
00347
00348 void
00349 __db_metaswap(pg)
00350 PAGE *pg;
00351 {
00352 u_int8_t *p;
00353
00354 p = (u_int8_t *)pg;
00355
00356
00357 SWAP32(p);
00358 SWAP32(p);
00359 SWAP32(p);
00360 SWAP32(p);
00361 SWAP32(p);
00362 SWAP32(p);
00363 p += 4;
00364 SWAP32(p);
00365 SWAP32(p);
00366 SWAP32(p);
00367 SWAP32(p);
00368 SWAP32(p);
00369 SWAP32(p);
00370 }
00371
00372
00373
00374
00375
00376
00377
00378
00379 int
00380 __db_byteswap(dbenv, dbp, pg, h, pagesize, pgin)
00381 DB_ENV *dbenv;
00382 DB *dbp;
00383 db_pgno_t pg;
00384 PAGE *h;
00385 size_t pagesize;
00386 int pgin;
00387 {
00388 BINTERNAL *bi;
00389 BKEYDATA *bk;
00390 BOVERFLOW *bo;
00391 RINTERNAL *ri;
00392 db_indx_t i, *inp, len, tmp;
00393 u_int8_t *p, *end;
00394
00395 COMPQUIET(pg, 0);
00396
00397 inp = P_INP(dbp, h);
00398 if (pgin) {
00399 M_32_SWAP(h->lsn.file);
00400 M_32_SWAP(h->lsn.offset);
00401 M_32_SWAP(h->pgno);
00402 M_32_SWAP(h->prev_pgno);
00403 M_32_SWAP(h->next_pgno);
00404 M_16_SWAP(h->entries);
00405 M_16_SWAP(h->hf_offset);
00406 }
00407
00408 switch (h->type) {
00409 case P_HASH:
00410 for (i = 0; i < NUM_ENT(h); i++) {
00411 if (pgin)
00412 M_16_SWAP(inp[i]);
00413
00414 switch (HPAGE_TYPE(dbp, h, i)) {
00415 case H_KEYDATA:
00416 break;
00417 case H_DUPLICATE:
00418 len = LEN_HKEYDATA(dbp, h, pagesize, i);
00419 p = HKEYDATA_DATA(P_ENTRY(dbp, h, i));
00420 for (end = p + len; p < end;) {
00421 if (pgin) {
00422 P_16_SWAP(p);
00423 memcpy(&tmp,
00424 p, sizeof(db_indx_t));
00425 p += sizeof(db_indx_t);
00426 } else {
00427 memcpy(&tmp,
00428 p, sizeof(db_indx_t));
00429 SWAP16(p);
00430 }
00431 p += tmp;
00432 SWAP16(p);
00433 }
00434 break;
00435 case H_OFFDUP:
00436 p = HOFFPAGE_PGNO(P_ENTRY(dbp, h, i));
00437 SWAP32(p);
00438 break;
00439 case H_OFFPAGE:
00440 p = HOFFPAGE_PGNO(P_ENTRY(dbp, h, i));
00441 SWAP32(p);
00442 SWAP32(p);
00443 break;
00444 default:
00445 return (__db_pgfmt(dbenv, pg));
00446 }
00447
00448 }
00449
00450
00451
00452
00453
00454
00455
00456 if (!pgin)
00457 for (i = 0; i < NUM_ENT(h); i++)
00458 M_16_SWAP(inp[i]);
00459 break;
00460 case P_LBTREE:
00461 case P_LDUP:
00462 case P_LRECNO:
00463 for (i = 0; i < NUM_ENT(h); i++) {
00464 if (pgin)
00465 M_16_SWAP(inp[i]);
00466
00467
00468
00469
00470
00471 if (h->type == P_LBTREE && i > 1) {
00472 if (pgin) {
00473 if (inp[i] == inp[i - 2])
00474 continue;
00475 } else {
00476 M_16_SWAP(inp[i]);
00477 if (inp[i] == inp[i - 2])
00478 continue;
00479 M_16_SWAP(inp[i]);
00480 }
00481 }
00482
00483 bk = GET_BKEYDATA(dbp, h, i);
00484 switch (B_TYPE(bk->type)) {
00485 case B_KEYDATA:
00486 M_16_SWAP(bk->len);
00487 break;
00488 case B_DUPLICATE:
00489 case B_OVERFLOW:
00490 bo = (BOVERFLOW *)bk;
00491 M_32_SWAP(bo->pgno);
00492 M_32_SWAP(bo->tlen);
00493 break;
00494 default:
00495 return (__db_pgfmt(dbenv, pg));
00496 }
00497
00498 if (!pgin)
00499 M_16_SWAP(inp[i]);
00500 }
00501 break;
00502 case P_IBTREE:
00503 for (i = 0; i < NUM_ENT(h); i++) {
00504 if (pgin)
00505 M_16_SWAP(inp[i]);
00506
00507 bi = GET_BINTERNAL(dbp, h, i);
00508 M_16_SWAP(bi->len);
00509 M_32_SWAP(bi->pgno);
00510 M_32_SWAP(bi->nrecs);
00511
00512 switch (B_TYPE(bi->type)) {
00513 case B_KEYDATA:
00514 break;
00515 case B_DUPLICATE:
00516 case B_OVERFLOW:
00517 bo = (BOVERFLOW *)bi->data;
00518 M_32_SWAP(bo->pgno);
00519 M_32_SWAP(bo->tlen);
00520 break;
00521 default:
00522 return (__db_pgfmt(dbenv, pg));
00523 }
00524
00525 if (!pgin)
00526 M_16_SWAP(inp[i]);
00527 }
00528 break;
00529 case P_IRECNO:
00530 for (i = 0; i < NUM_ENT(h); i++) {
00531 if (pgin)
00532 M_16_SWAP(inp[i]);
00533
00534 ri = GET_RINTERNAL(dbp, h, i);
00535 M_32_SWAP(ri->pgno);
00536 M_32_SWAP(ri->nrecs);
00537
00538 if (!pgin)
00539 M_16_SWAP(inp[i]);
00540 }
00541 break;
00542 case P_OVERFLOW:
00543 case P_INVALID:
00544
00545 break;
00546 default:
00547 return (__db_pgfmt(dbenv, pg));
00548 }
00549
00550 if (!pgin) {
00551
00552 M_32_SWAP(h->lsn.file);
00553 M_32_SWAP(h->lsn.offset);
00554 M_32_SWAP(h->pgno);
00555 M_32_SWAP(h->prev_pgno);
00556 M_32_SWAP(h->next_pgno);
00557 M_16_SWAP(h->entries);
00558 M_16_SWAP(h->hf_offset);
00559 }
00560 return (0);
00561 }