Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  NSSBenchTest.cpp

  Sprache: C
 

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include <string>

#include "gtest/gtest.h"
#include "gtest/MozGTestBench.h"  // For MOZ_GTEST_BENCH
#include "nss.h"
#include "ScopedNSSTypes.h"

namespace nss_test {

#define WARMUP (0ull)
#define KILOBYTE (1'024ull)
#define MEGABYTE (KILOBYTE * KILOBYTE)

template <CK_MECHANISM_TYPE MECH>
class SymmetricKeyTest : public testing::Test {
 protected:
  mozilla::UniquePK11SymKey sym_key;

  void SetUp() override {
    if (!NSS_IsInitialized()) {
      ASSERT_EQ(NSS_NoDB_Init(nullptr), SECSuccess);
    }

    mozilla::UniquePK11SlotInfo slot(PK11_GetInternalSlot());
    ASSERT_TRUE(!!slot);

    sym_key = mozilla::UniquePK11SymKey(
        PK11_KeyGen(slot.get(), MECH, nullptr, 16, nullptr));
    ASSERT_TRUE(!!sym_key);
  }
};

template <CK_MECHANISM_TYPE TYPE>
class KeyPairTest : public testing::Test {
 protected:
  mozilla::UniqueSECKEYPrivateKey priv_key;
  mozilla::UniqueSECKEYPublicKey pub_key;

  virtual void* MakeParams() = 0;

  void SetUp() override {
    if (!NSS_IsInitialized()) {
      ASSERT_EQ(NSS_NoDB_Init(nullptr), SECSuccess);
    }

    mozilla::UniquePK11SlotInfo slot(PK11_GetInternalSlot());
    ASSERT_TRUE(!!slot);

    priv_key = mozilla::UniqueSECKEYPrivateKey(PK11_GenerateKeyPair(
        slot.get(), TYPE, MakeParams(), TempPtrToSetter(&pub_key), PR_FALSE,
        PR_TRUE, nullptr));

    ASSERT_TRUE(!!priv_key);
    ASSERT_TRUE(!!pub_key);
  }
};

template <SECOidTag TAG>
class DigestTest : public testing::Test {
 protected:
  mozilla::UniquePK11Context context;

  void SetUp() override {
    if (!NSS_IsInitialized()) {
      ASSERT_EQ(NSS_NoDB_Init(nullptr), SECSuccess);
    }

    context = mozilla::UniquePK11Context(PK11_CreateDigestContext(TAG));
    ASSERT_TRUE(!!context);
  }
};

class BenchRunner : public testing::WithParamInterface<size_t> {
 public:
  virtual void Warmup() = 0;
  virtual void RunWithSize(size_t size) = 0;

  void Runner() {
    const size_t& size(GetParam());

    if (size == 0) {
      return Warmup();
    }

    RunWithSize(size);
  }

  const char* SuiteName() const {
    const char* instantiation =
        testing::UnitTest::GetInstance()->current_test_suite()->name();
    const char* suite = strchr(instantiation, '/');
    return suite ? suite + 1 : instantiation;
  }

  const char* TestName() const {
    const char* test =
        testing::UnitTest::GetInstance()->current_test_info()->name();
    const char* size = strchr(test, '/');
    return size ? size + 1 : test;
  }
};

class BenchEncryptRunner : public BenchRunner {
 public:
  void Warmup() override {
    std::vector<uint8_t> data(KILOBYTE);
    // data size + tag size
    std::vector<uint8_t> output(KILOBYTE + 16);
    EncryptData(data, output);
    DecryptData(output, data);
  }

  void RunWithSize(size_t size) override {
    std::vector<uint8_t> data(size);
    std::vector<uint8_t> encrypted(size + 16ull), decrypted(size);

    PK11_GenerateRandom(data.data(), data.size());

    mozilla::GTestBench(
        SuiteName(), (std::string(TestName()) + "_encrypt").c_str(),
        ([this, &data, &encrypted] { this->EncryptData(data, encrypted); }));
    mozilla::GTestBench(SuiteName(),
                        (std::string(TestName()) + "_decrypt").c_str(),
                        ([this, &encrypted, &decrypted] {
                          this->DecryptData(encrypted, decrypted);
                        }));
    ASSERT_EQ(data, decrypted);
  }

  virtual void EncryptData(std::vector<uint8_t>& data,
                           std::vector<uint8_t>& output) = 0;
  virtual void DecryptData(std::vector<uint8_t>& data,
                           std::vector<uint8_t>& output) = 0;
};

class BenchDigestRunner : public BenchRunner {
 public:
  void Warmup() override {
    std::vector<uint8_t> data(KILOBYTE);
    std::vector<uint8_t> output(DigestedSize());
    DigestData(data, output);
  }

  void RunWithSize(size_t size) override {
    std::vector<uint8_t> data(size);
    std::vector<uint8_t> encrypted(DigestedSize());

    PK11_GenerateRandom(data.data(), data.size());

    mozilla::GTestBench(SuiteName(), TestName(), ([this, &data, &encrypted] {
                          this->DigestData(data, encrypted);
                        }));
  }

  virtual size_t DigestedSize() = 0;
  virtual void DigestData(std::vector<uint8_t>& data,
                          std::vector<uint8_t>& output) = 0;
};

class BenchSignRunner : public BenchRunner {
 public:
  void Warmup() override {
    std::vector<uint8_t> data(64);
    std::vector<uint8_t> output(SignatureSize());
    SignData(data, output);
  }

  void RunWithSize(size_t size) override {
    std::vector<uint8_t> data(size);
    std::vector<uint8_t> sign(SignatureSize());

    PK11_GenerateRandom(data.data(), data.size());

    bool verified = false;

    mozilla::GTestBench(SuiteName(),
                        (std::string(TestName()) + "_sign").c_str(),
                        ([this, &data, &sign] { this->SignData(data, sign); }));
    mozilla::GTestBench(SuiteName(),
                        (std::string(TestName()) + "_verify").c_str(),
                        ([this, &data, &sign, &verified] {
                          verified = this->VerifyData(data, sign);
                        }));
    ASSERT_TRUE(verified);
  }

  virtual size_t SignatureSize() const = 0;
  virtual void SignData(std::vector<uint8_t>& data,
                        std::vector<uint8_t>& output) = 0;
  virtual bool VerifyData(std::vector<uint8_t>& data,
                          std::vector<uint8_t>& signature) = 0;
};

class BenchECDHRunner : public BenchRunner {
 public:
  void Warmup() override { mozilla::UniquePK11SymKey(this->DeriveKey()); }

  void RunWithSize(size_t size) override {
    mozilla::UniquePK11SymKey key = nullptr;
    mozilla::GTestBench(SuiteName(), "derive",
                        ([this, &key] { key.reset(this->DeriveKey()); }));
    ASSERT_TRUE(!!key);
  }

  virtual PK11SymKey* DeriveKey() = 0;
};

// ===============================================
// ------------------- Encrypt -------------------
// ===============================================

template <CK_MECHANISM_TYPE MECH>
class BenchEncrypt : public SymmetricKeyTest<MECH>, public BenchEncryptRunner {
  virtual SECItem MakeParams() = 0;

 public:
  void SetUp() override { SymmetricKeyTest<MECH>::SetUp(); }

  void EncryptData(std::vector<uint8_t>& data,
                   std::vector<uint8_t>& output) override {
    SECItem params = MakeParams();

    unsigned int output_len = 0;
    SECStatus rv =
        PK11_Encrypt(this->sym_key.get(), MECH, ¶ms, output.data(),
                     &output_len, output.size(), data.data(), data.size());

    ASSERT_EQ(rv, SECSuccess);

    output.resize(output_len);
  }

  void DecryptData(std::vector<uint8_t>& data,
                   std::vector<uint8_t>& output) override {
    SECItem params = MakeParams();

    unsigned int output_len = 0;
    SECStatus rv =
        PK11_Decrypt(this->sym_key.get(), MECH, ¶ms, output.data(),
                     &output_len, output.size(), data.data(), data.size());

    ASSERT_EQ(rv, SECSuccess);

    output.resize(output_len);
  }
};

class BenchEncrypt_AES_GCM : public BenchEncrypt<CKM_AES_GCM> {
  std::vector<uint8_t> iv = std::vector<uint8_t>(160);
  std::vector<uint8_t> aad = std::vector<uint8_t>(0);
  CK_NSS_GCM_PARAMS gcm_params;

 protected:
  SECItem MakeParams() override {
    gcm_params.pIv = iv.data();
    gcm_params.ulIvLen = iv.size();
    gcm_params.pAAD = aad.data();
    gcm_params.ulAADLen = aad.size();
    gcm_params.ulTagBits = 128;

    SECItem params = {siBuffer, reinterpret_cast<unsigned char*>(&gcm_params),
                      sizeof(gcm_params)};
    return params;
  }
};

class BenchEncrypt_CHACHA20_POLY1305
    : public BenchEncrypt<CKM_CHACHA20_POLY1305> {
  std::vector<uint8_t> iv = std::vector<uint8_t>(12);
  std::vector<uint8_t> aad = std::vector<uint8_t>(16);
  CK_SALSA20_CHACHA20_POLY1305_PARAMS chacha_params;

 protected:
  SECItem MakeParams() override {
    chacha_params.pNonce = iv.data();
    chacha_params.ulNonceLen = iv.size();
    chacha_params.pAAD = aad.data();
    chacha_params.ulAADLen = aad.size();

    SECItem params = {siBuffer,
                      reinterpret_cast<unsigned char*>(&chacha_params),
                      sizeof(chacha_params)};

    return params;
  }
};

class BenchEncrypt_CHACHA20 : public BenchEncrypt<CKM_CHACHA20> {
  std::vector<uint8_t> iv = std::vector<uint8_t>(12);
  uint32_t counter;
  CK_CHACHA20_PARAMS chacha_params;

 protected:
  SECItem MakeParams() override {
    chacha_params.pBlockCounter = reinterpret_cast<CK_BYTE_PTR>(&counter);
    chacha_params.blockCounterBits = 32;
    chacha_params.pNonce = iv.data();
    chacha_params.ulNonceBits = iv.size();
    SECItem params = {siBuffer,
                      reinterpret_cast<unsigned char*>(&chacha_params),
                      sizeof(chacha_params)};

    return params;
  }
};

// ===============================================
// -------------------  Digest -------------------
// ===============================================

template <SECOidTag TAG, size_t DIGEST_SIZE>
class BenchDigest : public DigestTest<TAG>, public BenchDigestRunner {
 public:
  size_t DigestedSize() override { return DIGEST_SIZE; }

  void DigestData(std::vector<uint8_t>& data,
                  std::vector<uint8_t>& output) override {
    SECStatus rv = PK11_DigestBegin(this->context.get());
    ASSERT_EQ(rv, SECSuccess);

    rv = PK11_DigestOp(this->context.get(), data.data(), data.size());
    ASSERT_EQ(rv, SECSuccess);

    unsigned int output_len = 0;

    rv = PK11_DigestFinal(this->context.get(), output.data(), &output_len,
                          output.size());
    ASSERT_EQ(rv, SECSuccess);

    output.resize(output_len);
  }
};

using BenchDigest_SHA256 = BenchDigest<SEC_OID_SHA256, SHA256_LENGTH>;
using BenchDigest_SHA512 = BenchDigest<SEC_OID_SHA512, SHA512_LENGTH>;

template <CK_MECHANISM_TYPE MECH, size_t DIGEST_SIZE>
class SymmetricKeySignTest : public SymmetricKeyTest<MECH>,
                             public BenchDigestRunner {
 public:
  size_t DigestedSize() override { return DIGEST_SIZE; }

  void DigestData(std::vector<uint8_t>& data,
                  std::vector<uint8_t>& output) override {
    SECItem hash = {siBuffer, data.data(),
                    static_cast<unsigned int>(data.size())};
    SECItem out = {siBuffer, output.data(),
                   static_cast<unsigned int>(output.size())};

    SECStatus rv =
        PK11_SignWithSymKey(this->sym_key.get(), MECH, nullptr, &out, &hash);
    ASSERT_EQ(rv, SECSuccess);
  }
};

using BenchSign_SHA256_HMAC =
    SymmetricKeySignTest<CKM_SHA256_HMAC, SHA256_LENGTH>;
using BenchSign_SHA384_HMAC =
    SymmetricKeySignTest<CKM_SHA384_HMAC, SHA384_LENGTH>;
using BenchSign_SHA512_HMAC =
    SymmetricKeySignTest<CKM_SHA512_HMAC, SHA512_LENGTH>;
using BenchSign_SHA3_224_HMAC =
    SymmetricKeySignTest<CKM_SHA3_224_HMAC, SHA3_224_LENGTH>;
using BenchSign_SHA3_256_HMAC =
    SymmetricKeySignTest<CKM_SHA3_256_HMAC, SHA3_256_LENGTH>;
using BenchSign_SHA3_384_HMAC =
    SymmetricKeySignTest<CKM_SHA3_384_HMAC, SHA3_384_LENGTH>;
using BenchSign_SHA3_512_HMAC =
    SymmetricKeySignTest<CKM_SHA3_512_HMAC, SHA3_512_LENGTH>;

// ===============================================
// --------------- Sign and verify ---------------
// ===============================================

template <CK_MECHANISM_TYPE TYPE>
class KeyPairSignTest : public KeyPairTest<TYPE>, public BenchSignRunner {
 protected:
  size_t SignatureSize() const override {
    return PK11_SignatureLen(this->priv_key.get());
  }

  void SignData(std::vector<uint8_t>& data,
                std::vector<uint8_t>& output) override {
    SECItem hash = {siBuffer, data.data(),
                    static_cast<unsigned int>(data.size())};
    SECItem out = {siBuffer, output.data(),
                   static_cast<unsigned int>(output.size())};

    SECStatus rv = PK11_Sign(this->priv_key.get(), &out, &hash);
    ASSERT_EQ(rv, SECSuccess);
  }

  bool VerifyData(std::vector<uint8_t>& data,
                  std::vector<uint8_t>& signature) override {
    SECItem dat = {siBuffer, data.data(),
                   static_cast<unsigned int>(data.size())};
    SECItem sig = {siBuffer, signature.data(),
                   static_cast<unsigned int>(signature.size())};

    SECStatus rv = PK11_Verify(this->pub_key.get(), &sig, &dat, nullptr);
    return rv == SECSuccess;
  }
};

template <SECOidTag CURVE>
class BenchSignEC : public KeyPairSignTest<CKM_EC_KEY_PAIR_GEN> {
  SECKEYECParams params;
  std::unique_ptr<uint8_t[]> extra;

 public:
  void* MakeParams() {
    /* For the case of ED curve_oid contains a EdDSA OID. */
    SECOidData* curve = SECOID_FindOIDByTag(CURVE);

    size_t plen = curve->oid.len + 2;
    extra.reset(new uint8_t[plen]);
    extra[0] = SEC_ASN1_OBJECT_ID;
    extra[1] = static_cast<uint8_t>(curve->oid.len);
    memcpy(&extra[2], curve->oid.data, curve->oid.len);

    params = {siBuffer, extra.get(), static_cast<unsigned int>(plen)};

    return ¶ms;
  }
};

using BenchSign_P256 = BenchSignEC<SEC_OID_SECG_EC_SECP256R1>;
using BenchSign_P384 = BenchSignEC<SEC_OID_SECG_EC_SECP384R1>;
using BenchSign_P521 = BenchSignEC<SEC_OID_SECG_EC_SECP521R1>;

template <size_t KEY_SIZE>
class BenchSignRSA : public KeyPairSignTest<CKM_RSA_PKCS_KEY_PAIR_GEN> {
  PK11RSAGenParams rsa_params;

 public:
  void* MakeParams() {
    rsa_params.keySizeInBits = KEY_SIZE;
    rsa_params.pe = 0x10001;

    return &rsa_params;
  }
};

using BenchSign_RSA1024 = BenchSignRSA<1024>;
using BenchSign_RSA2048 = BenchSignRSA<2048>;
using BenchSign_RSA4096 = BenchSignRSA<4096>;

// ===============================================
// --------- Diffie-Hellman key exchange ---------
// ===============================================

template <SECOidTag CURVE, CK_MECHANISM_TYPE TARGET>
class BenchECDH : public KeyPairTest<CKM_EC_KEY_PAIR_GEN>,
                  public BenchECDHRunner {
  SECKEYECParams params;
  std::unique_ptr<uint8_t[]> extra;

 public:
  void* MakeParams() override {
    /* For the case of ED curve_oid contains a EdDSA OID. */
    SECOidData* curve = SECOID_FindOIDByTag(CURVE);

    size_t plen = curve->oid.len + 2;
    extra.reset(new uint8_t[plen]);
    extra[0] = SEC_ASN1_OBJECT_ID;
    extra[1] = static_cast<uint8_t>(curve->oid.len);
    memcpy(&extra[2], curve->oid.data, curve->oid.len);

    params = {siBuffer, extra.get(), static_cast<unsigned int>(plen)};

    return ¶ms;
  }

  PK11SymKey* DeriveKey() override {
    return PK11_PubDeriveWithKDF(
        this->priv_key.get(), this->pub_key.get(), false, nullptr, nullptr,
        CKM_ECDH1_DERIVE, TARGET, CKA_DERIVE, 0, CKD_NULL, nullptr, nullptr);
  }
};

using BenchECDH_P256_SHA256 =
    BenchECDH<SEC_OID_SECG_EC_SECP256R1, CKM_SHA256_HMAC>;
using BenchECDH_P384_SHA256 =
    BenchECDH<SEC_OID_SECG_EC_SECP384R1, CKM_SHA256_HMAC>;
using BenchECDH_P521_SHA256 =
    BenchECDH<SEC_OID_SECG_EC_SECP521R1, CKM_SHA256_HMAC>;

// ===============================================
// ------------------ Harnesses ------------------
// ===============================================

std::string MakeTestName(const testing::TestParamInfo<size_t>& info) {
  if (info.param == 0) {
    return "warmup";
  }

  if (info.param < KILOBYTE) {
    return std::to_string(info.param);
  }

  if (info.param < MEGABYTE) {
    return std::to_string(info.param / KILOBYTE) + "k";
  }

  return std::to_string(info.param / MEGABYTE) + "m";
}

#define NSS_BENCH_P(suite, params)                                        \
  TEST_P(suite, Run) { Runner(); }                                        \
  INSTANTIATE_TEST_SUITE_P(psm_##suite, suite, testing::ValuesIn(params), \
                           MakeTestName);

static const size_t BENCH_ENCRYPT_SIZE[] = {
    WARMUP, KILOBYTE, 16 * KILOBYTE, MEGABYTE, 16 * MEGABYTE, 128 * MEGABYTE};
// These fail because the treeherder instances run out of memory
//
// 512 * MEGABYTE, GIGABYTE - MEGABYTE, GIGABYTE,
//
// These fail because some of the SHA3 HMAC suites time out
//
// 4 * GIGABYTE - MEGABYTE, 4 * GIGABYTE - 32,
//
// These fail because the size parameters in PK11_Encrypt/PK11_Decrypt
// are unsigned int, i.e. 32bits. So any data size + tag size > 4GiB will
// fail
//
// 4 * GIGABYTE - 1, 4 * GIGABYTE, 4 * GIGABYTE + MEGABYTE, 16 * GIGABYTE,

static const size_t BENCH_DH_SIZE[] = {WARMUP, 1};
static const size_t BENCH_RSA1024_SIZE[] = {WARMUP, 3264117};
static const size_t BENCH_RSA2048_SIZE[] = {WARMUP, 3264128245};
static const size_t BENCH_RSA4096_SIZE[] = {WARMUP, 3264128256501};

NSS_BENCH_P(BenchEncrypt_AES_GCM, BENCH_ENCRYPT_SIZE)
NSS_BENCH_P(BenchEncrypt_CHACHA20, BENCH_ENCRYPT_SIZE)
NSS_BENCH_P(BenchEncrypt_CHACHA20_POLY1305, BENCH_ENCRYPT_SIZE)

NSS_BENCH_P(BenchDigest_SHA256, BENCH_ENCRYPT_SIZE)
NSS_BENCH_P(BenchDigest_SHA512, BENCH_ENCRYPT_SIZE)
NSS_BENCH_P(BenchSign_SHA256_HMAC, BENCH_ENCRYPT_SIZE)
NSS_BENCH_P(BenchSign_SHA384_HMAC, BENCH_ENCRYPT_SIZE)
NSS_BENCH_P(BenchSign_SHA512_HMAC, BENCH_ENCRYPT_SIZE)
NSS_BENCH_P(BenchSign_SHA3_224_HMAC, BENCH_ENCRYPT_SIZE)
NSS_BENCH_P(BenchSign_SHA3_256_HMAC, BENCH_ENCRYPT_SIZE)
NSS_BENCH_P(BenchSign_SHA3_384_HMAC, BENCH_ENCRYPT_SIZE)
NSS_BENCH_P(BenchSign_SHA3_512_HMAC, BENCH_ENCRYPT_SIZE)

NSS_BENCH_P(BenchSign_P256, BENCH_ENCRYPT_SIZE)
NSS_BENCH_P(BenchSign_P384, BENCH_ENCRYPT_SIZE)
NSS_BENCH_P(BenchSign_P521, BENCH_ENCRYPT_SIZE)

NSS_BENCH_P(BenchECDH_P256_SHA256, BENCH_DH_SIZE)
NSS_BENCH_P(BenchECDH_P384_SHA256, BENCH_DH_SIZE)
NSS_BENCH_P(BenchECDH_P521_SHA256, BENCH_DH_SIZE)

NSS_BENCH_P(BenchSign_RSA1024, BENCH_RSA1024_SIZE)
NSS_BENCH_P(BenchSign_RSA2048, BENCH_RSA2048_SIZE)
NSS_BENCH_P(BenchSign_RSA4096, BENCH_RSA4096_SIZE)

}  // namespace nss_test

Messung V0.5 in Prozent
C=93 H=95 G=93

¤ Dauer der Verarbeitung: 0.6 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=277311
#Domains=752002