From: Radoslaw Zarzynski Date: Tue, 8 May 2018 13:08:55 +0000 (+0200) Subject: tests/crypto: add tests for the no-bl encrypt/decrypt, part 2. X-Git-Tag: v14.0.0~67^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=2535d11713aa837015e5028923ac97a271f41081;p=ceph.git tests/crypto: add tests for the no-bl encrypt/decrypt, part 2. Signed-off-by: Radoslaw Zarzynski --- diff --git a/src/test/crypto.cc b/src/test/crypto.cc index bdc6773da52fc..5190a0bfe1671 100644 --- a/src/test/crypto.cc +++ b/src/test/crypto.cc @@ -11,6 +11,12 @@ #include "common/ceph_context.h" #include "global/global_context.h" +#ifdef USE_NSS +# include +# include +# include +#endif // USE_NSS + class CryptoEnvironment: public ::testing::Environment { public: void SetUp() override { @@ -18,6 +24,183 @@ public: } }; +#ifdef USE_NSS +// when we say AES, we mean AES-128 +# define AES_KEY_LEN 16 +# define AES_BLOCK_LEN 16 + +static int nss_aes_operation(CK_ATTRIBUTE_TYPE op, + CK_MECHANISM_TYPE mechanism, + PK11SymKey *key, + SECItem *param, + const bufferlist& in, bufferlist& out, + std::string *error) +{ + // sample source said this has to be at least size of input + 8, + // but i see 15 still fail with SEC_ERROR_OUTPUT_LEN + bufferptr out_tmp(in.length()+16); + bufferlist incopy; + + SECStatus ret; + int written; + unsigned char *in_buf; + + PK11Context *ectx; + ectx = PK11_CreateContextBySymKey(mechanism, op, key, param); + assert(ectx); + + incopy = in; // it's a shallow copy! + in_buf = (unsigned char*)incopy.c_str(); + ret = PK11_CipherOp(ectx, + (unsigned char*)out_tmp.c_str(), &written, out_tmp.length(), + in_buf, in.length()); + if (ret != SECSuccess) { + PK11_DestroyContext(ectx, PR_TRUE); + if (error) { + ostringstream oss; + oss << "NSS AES failed: " << PR_GetError(); + *error = oss.str(); + } + return -1; + } + + unsigned int written2; + ret = PK11_DigestFinal(ectx, + (unsigned char*)out_tmp.c_str()+written, &written2, + out_tmp.length()-written); + PK11_DestroyContext(ectx, PR_TRUE); + if (ret != SECSuccess) { + if (error) { + ostringstream oss; + oss << "NSS AES final round failed: " << PR_GetError(); + *error = oss.str(); + } + return -1; + } + + out_tmp.set_length(written + written2); + out.append(out_tmp); + return 0; +} + +class LegacyCryptoAESKeyHandler : public CryptoKeyHandler { + CK_MECHANISM_TYPE mechanism; + PK11SlotInfo *slot; + PK11SymKey *key; + SECItem *param; + +public: + LegacyCryptoAESKeyHandler() + : CryptoKeyHandler(CryptoKeyHandler::BLOCK_SIZE_16B()), + mechanism(CKM_AES_CBC_PAD), + slot(NULL), + key(NULL), + param(NULL) {} + ~LegacyCryptoAESKeyHandler() override { + SECITEM_FreeItem(param, PR_TRUE); + if (key) + PK11_FreeSymKey(key); + if (slot) + PK11_FreeSlot(slot); + } + + int init(const bufferptr& s, string& err) { + ostringstream oss; + const int ret = init(s, oss); + err = oss.str(); + return ret; + } + + int init(const bufferptr& s, ostringstream& err) { + secret = s; + + slot = PK11_GetBestSlot(mechanism, NULL); + if (!slot) { + err << "cannot find NSS slot to use: " << PR_GetError(); + return -1; + } + + SECItem keyItem; + keyItem.type = siBuffer; + keyItem.data = (unsigned char*)secret.c_str(); + keyItem.len = secret.length(); + key = PK11_ImportSymKey(slot, mechanism, PK11_OriginUnwrap, CKA_ENCRYPT, + &keyItem, NULL); + if (!key) { + err << "cannot convert AES key for NSS: " << PR_GetError(); + return -1; + } + + SECItem ivItem; + ivItem.type = siBuffer; + // losing constness due to SECItem.data; IV should never be + // modified, regardless + ivItem.data = (unsigned char*)CEPH_AES_IV; + ivItem.len = sizeof(CEPH_AES_IV); + + param = PK11_ParamFromIV(mechanism, &ivItem); + if (!param) { + err << "cannot set NSS IV param: " << PR_GetError(); + return -1; + } + + return 0; + } + + using CryptoKeyHandler::encrypt; + using CryptoKeyHandler::decrypt; + + int encrypt(const bufferlist& in, + bufferlist& out, std::string *error) const override { + return nss_aes_operation(CKA_ENCRYPT, mechanism, key, param, in, out, error); + } + int decrypt(const bufferlist& in, + bufferlist& out, std::string *error) const override { + return nss_aes_operation(CKA_DECRYPT, mechanism, key, param, in, out, error); + } +}; + +TEST(AES, ValidateLegacy) { + CryptoHandler* const newh = \ + g_ceph_context->get_crypto_handler(CEPH_CRYPTO_AES); + + const char secret_s[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }; + ceph::bufferptr secret(secret_s, sizeof(secret_s)); + + std::string error; + std::unique_ptr newkh( + newh->get_key_handler(secret, error)); + ASSERT_TRUE(error.empty()); + + LegacyCryptoAESKeyHandler oldkh; + oldkh.init(secret, error); + ASSERT_TRUE(error.empty()); + + unsigned char plaintext_s[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + }; + ceph::bufferlist plaintext; + plaintext.append((char *)plaintext_s, sizeof(plaintext_s)); + + ceph::bufferlist ciphertext; + int r = newkh->encrypt(plaintext, ciphertext, &error); + ASSERT_EQ(r, 0); + ASSERT_EQ(error, ""); + + ceph::bufferlist restored_plaintext; + r = oldkh.decrypt(ciphertext, restored_plaintext, &error); + ASSERT_EQ(r, 0); + ASSERT_TRUE(error.empty()); + + ASSERT_EQ(plaintext, restored_plaintext); +} + +#endif // USE_NSS + TEST(AES, ValidateSecret) { CryptoHandler *h = g_ceph_context->get_crypto_handler(CEPH_CRYPTO_AES); int l;