/*- * Copyright (c) 2014-2016 MongoDB, Inc. * Copyright (c) 2008-2014 WiredTiger, Inc. * All rights reserved. * * See the file LICENSE for redistribution information. */ #include "wt_internal.h" /* * __wt_decrypt -- * Common code to decrypt and verify the encrypted data in a * WT_ITEM and return the decrypted buffer. */ int __wt_decrypt(WT_SESSION_IMPL *session, WT_ENCRYPTOR *encryptor, size_t skip, WT_ITEM *in, WT_ITEM *out) { size_t encryptor_data_len, result_len; uint32_t encrypt_len; uint8_t *dst, *src; encrypt_len = WT_STORE_SIZE(*((uint32_t *)((uint8_t *)in->data + skip))); #ifdef WORDS_BIGENDIAN encrypt_len = __wt_bswap32(encrypt_len); #endif if (encrypt_len > in->size) WT_RET_MSG(session, WT_ERROR, "corrupted encrypted item: padded size less than " "actual size"); /* * We're allocating the number of bytes we're expecting * from decryption plus the unencrypted header. */ WT_RET(__wt_buf_initsize(session, out, encrypt_len)); src = (uint8_t *)in->data + skip + WT_ENCRYPT_LEN_SIZE; encryptor_data_len = encrypt_len - (skip + WT_ENCRYPT_LEN_SIZE); dst = (uint8_t *)out->mem + skip; WT_RET(encryptor->decrypt(encryptor, &session->iface, src, encryptor_data_len, dst, encryptor_data_len, &result_len)); /* * We require encryption to be byte for byte. It should not expand * the data. */ WT_ASSERT(session, result_len <= encryptor_data_len); /* * Copy in the skipped header bytes. */ memcpy(out->mem, in->data, skip); /* * Set the real result length in the output buffer including the skipped * header size. The encryptor may have done its own padding so the * returned result length is the real data length after decryption * removes any of its padding. */ out->size = result_len + skip; return (0); } /* * __wt_encrypt -- * Common code to encrypt a WT_ITEM and return the encrypted buffer. */ int __wt_encrypt(WT_SESSION_IMPL *session, WT_KEYED_ENCRYPTOR *kencryptor, size_t skip, WT_ITEM *in, WT_ITEM *out) { size_t dst_len, result_len, src_len; uint32_t *unpadded_lenp; uint8_t *dst, *src; /* Skip the header bytes of the source data. */ src = (uint8_t *)in->mem + skip; src_len = in->size - skip; unpadded_lenp = (uint32_t *)((uint8_t *)out->mem + skip); /* * Skip the header bytes and the length we store in the destination * data. Add in the encryptor size constant to the expected destination * length. */ dst = (uint8_t *)out->mem + skip + WT_ENCRYPT_LEN_SIZE; dst_len = src_len + kencryptor->size_const; WT_RET(kencryptor->encryptor->encrypt(kencryptor->encryptor, &session->iface, src, src_len, dst, dst_len, &result_len)); /* * We require encryption to be byte for byte. It should never expand * the data. */ WT_ASSERT(session, result_len <= dst_len); /* * The final result length includes the skipped lengths. */ result_len += skip + WT_ENCRYPT_LEN_SIZE; /* * Store original size so we know how much space is needed on the * decryption side. */ *unpadded_lenp = WT_STORE_SIZE(result_len); #ifdef WORDS_BIGENDIAN *unpadded_lenp = __wt_bswap32(*unpadded_lenp); #endif /* * Copy in the skipped header bytes, set the final data size. */ memcpy(out->mem, in->mem, skip); out->size = result_len; return (0); } /* * __wt_encrypt_size -- * Return the size needed for the destination buffer. */ void __wt_encrypt_size(WT_SESSION_IMPL *session, WT_KEYED_ENCRYPTOR *kencryptor, size_t incoming_size, size_t *sizep) { WT_UNUSED(session); if (sizep == NULL) return; *sizep = incoming_size + kencryptor->size_const + WT_ENCRYPT_LEN_SIZE; return; }