tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pk11_rsaencrypt_unittest.cc (7475B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include <algorithm>
      8 #include <cstdint>
      9 
     10 #include "cpputil.h"
     11 #include "cryptohi.h"
     12 #include "json_reader.h"
     13 #include "gtest/gtest.h"
     14 #include "limits.h"
     15 #include "nss.h"
     16 #include "nss_scoped_ptrs.h"
     17 #include "pk11pub.h"
     18 #include "databuffer.h"
     19 
     20 #include "testvectors/rsa_signature-vectors.h"
     21 #include "testvectors/rsaencrypt_bb2048-vectors.h"
     22 #include "testvectors/rsaencrypt_bb3072-vectors.h"
     23 
     24 namespace nss_test {
     25 
     26 class RsaDecryptWycheproofTest : public ::testing::Test {
     27 protected:
     28  void Run(const std::string& name) {
     29    WycheproofHeader(name, "RSAES-PKCS1-v1_5",
     30                     "rsaes_pkcs1_decrypt_schema.json",
     31                     [this](JsonReader& r) { RunGroup(r); });
     32  }
     33 
     34  void TestDecrypt(const RsaDecryptTestVector& vec) {
     35    SECItem pkcs8_item = {siBuffer, toUcharPtr(vec.priv_key.data()),
     36                          static_cast<unsigned int>(vec.priv_key.size())};
     37 
     38    ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
     39    EXPECT_NE(nullptr, slot);
     40 
     41    SECKEYPrivateKey* key = nullptr;
     42    SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey(
     43        slot.get(), &pkcs8_item, nullptr, nullptr, false, false, KU_ALL, &key,
     44        nullptr);
     45    ASSERT_EQ(SECSuccess, rv);
     46    ASSERT_NE(nullptr, key);
     47    ScopedSECKEYPrivateKey priv_key(key);
     48 
     49    // Decrypt
     50    std::vector<uint8_t> decrypted(PR_MAX(1, vec.ct.size()));
     51    unsigned int decrypted_len = 0;
     52    rv = PK11_PrivDecryptPKCS1(priv_key.get(), decrypted.data(), &decrypted_len,
     53                               decrypted.size(), vec.ct.data(), vec.ct.size());
     54 
     55    decrypted.resize(decrypted_len);
     56    if (vec.valid) {
     57      ASSERT_EQ(SECSuccess, rv);
     58      EXPECT_EQ(vec.msg, decrypted);
     59    } else if (vec.invalid_padding) {
     60      // If the padding is bad, decryption should succeed and produce
     61      // (pseudo)random output.
     62      ASSERT_EQ(SECSuccess, rv);
     63      ASSERT_NE(vec.msg, decrypted);
     64    } else {
     65      ASSERT_EQ(SECFailure, rv)
     66          << "Returned:" << DataBuffer(decrypted.data(), decrypted.size());
     67    }
     68  };
     69 
     70 private:
     71  void RunGroup(JsonReader& r) {
     72    std::vector<RsaDecryptTestVector> tests;
     73    std::vector<uint8_t> private_key;
     74    while (r.NextItem()) {
     75      std::string n = r.ReadLabel();
     76      if (n == "") {
     77        break;
     78      }
     79 
     80      if (n == "d" || n == "e" || n == "keysize" || n == "n" ||
     81          n == "privateKeyJwk" || n == "privateKeyPem") {
     82        r.SkipValue();
     83      } else if (n == "privateKeyPkcs8") {
     84        private_key = r.ReadHex();
     85      } else if (n == "type") {
     86        ASSERT_EQ("RsaesPkcs1Decrypt", r.ReadString());
     87      } else if (n == "tests") {
     88        WycheproofReadTests(r, &tests, ReadTestAttr, false,
     89                            [](RsaDecryptTestVector& t, const std::string&,
     90                               const std::vector<std::string>& flags) {
     91                              t.invalid_padding =
     92                                  std::find(flags.begin(), flags.end(),
     93                                            "InvalidPkcs1Padding") !=
     94                                  flags.end();
     95                            });
     96      } else {
     97        FAIL() << "unknown label in group: " << n;
     98      }
     99    }
    100 
    101    for (auto& t : tests) {
    102      std::cout << "Running test " << t.id << std::endl;
    103      t.priv_key = private_key;
    104      TestDecrypt(t);
    105    }
    106  }
    107 
    108  static void ReadTestAttr(RsaDecryptTestVector& t, const std::string& n,
    109                           JsonReader& r) {
    110    if (n == "msg") {
    111      t.msg = r.ReadHex();
    112    } else if (n == "ct") {
    113      t.ct = r.ReadHex();
    114    } else {
    115      FAIL() << "unsupported test case field: " << n;
    116    }
    117  }
    118 };
    119 
    120 TEST_F(RsaDecryptWycheproofTest, Rsa2048) { Run("rsa_pkcs1_2048"); }
    121 TEST_F(RsaDecryptWycheproofTest, Rsa3072) { Run("rsa_pkcs1_3072"); }
    122 TEST_F(RsaDecryptWycheproofTest, Rsa4096) { Run("rsa_pkcs1_4096"); }
    123 
    124 TEST_F(RsaDecryptWycheproofTest, Bb2048) {
    125  for (auto& t : kRsaBb2048Vectors) {
    126    RsaDecryptTestVector copy = t;
    127    copy.priv_key = kRsaBb2048;
    128    TestDecrypt(copy);
    129  }
    130 }
    131 TEST_F(RsaDecryptWycheproofTest, Bb2049) {
    132  for (auto& t : kRsaBb2049Vectors) {
    133    RsaDecryptTestVector copy = t;
    134    copy.priv_key = kRsaBb2049;
    135    TestDecrypt(copy);
    136  }
    137 }
    138 TEST_F(RsaDecryptWycheproofTest, Bb3072) {
    139  for (auto& t : kRsaBb3072Vectors) {
    140    RsaDecryptTestVector copy = t;
    141    copy.priv_key = kRsaBb3072;
    142    TestDecrypt(copy);
    143  }
    144 }
    145 
    146 TEST(RsaEncryptTest, MessageLengths) {
    147  const uint8_t spki[] = {
    148      0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
    149      0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81,
    150      0x89, 0x02, 0x81, 0x81, 0x00, 0xf8, 0xb8, 0x6c, 0x83, 0xb4, 0xbc, 0xd9,
    151      0xa8, 0x57, 0xc0, 0xa5, 0xb4, 0x59, 0x76, 0x8c, 0x54, 0x1d, 0x79, 0xeb,
    152      0x22, 0x52, 0x04, 0x7e, 0xd3, 0x37, 0xeb, 0x41, 0xfd, 0x83, 0xf9, 0xf0,
    153      0xa6, 0x85, 0x15, 0x34, 0x75, 0x71, 0x5a, 0x84, 0xa8, 0x3c, 0xd2, 0xef,
    154      0x5a, 0x4e, 0xd3, 0xde, 0x97, 0x8a, 0xdd, 0xff, 0xbb, 0xcf, 0x0a, 0xaa,
    155      0x86, 0x92, 0xbe, 0xb8, 0x50, 0xe4, 0xcd, 0x6f, 0x80, 0x33, 0x30, 0x76,
    156      0x13, 0x8f, 0xca, 0x7b, 0xdc, 0xec, 0x5a, 0xca, 0x63, 0xc7, 0x03, 0x25,
    157      0xef, 0xa8, 0x8a, 0x83, 0x58, 0x76, 0x20, 0xfa, 0x16, 0x77, 0xd7, 0x79,
    158      0x92, 0x63, 0x01, 0x48, 0x1a, 0xd8, 0x7b, 0x67, 0xf1, 0x52, 0x55, 0x49,
    159      0x4e, 0xd6, 0x6e, 0x4a, 0x5c, 0xd7, 0x7a, 0x37, 0x36, 0x0c, 0xde, 0xdd,
    160      0x8f, 0x44, 0xe8, 0xc2, 0xa7, 0x2c, 0x2b, 0xb5, 0xaf, 0x64, 0x4b, 0x61,
    161      0x07, 0x02, 0x03, 0x01, 0x00, 0x01,
    162  };
    163 
    164  // Import public key (use pre-generated for performance).
    165  SECItem spki_item = {siBuffer, toUcharPtr(spki), sizeof(spki)};
    166  ScopedCERTSubjectPublicKeyInfo cert_spki(
    167      SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item));
    168  ASSERT_TRUE(cert_spki);
    169  ScopedSECKEYPublicKey pub_key(SECKEY_ExtractPublicKey(cert_spki.get()));
    170  ASSERT_TRUE(pub_key);
    171 
    172  int mod_len = SECKEY_PublicKeyStrength(pub_key.get());
    173  ASSERT_TRUE(mod_len > 0);
    174 
    175  std::vector<uint8_t> ctxt(mod_len);
    176  unsigned int ctxt_len;
    177  std::vector<uint8_t> msg(mod_len, 0xff);
    178 
    179  // Test with valid inputs
    180  SECStatus rv =
    181      PK11_PubEncrypt(pub_key.get(), CKM_RSA_PKCS, nullptr, ctxt.data(),
    182                      &ctxt_len, mod_len, msg.data(), 1, nullptr);
    183  ASSERT_EQ(SECSuccess, rv);
    184 
    185  // Maximum message length is mod_len - miniumum padding (8B) - flags (3B)
    186  unsigned int max_msg_len = mod_len - 8 - 3;
    187  rv = PK11_PubEncrypt(pub_key.get(), CKM_RSA_PKCS, nullptr, ctxt.data(),
    188                       &ctxt_len, mod_len, msg.data(), max_msg_len, nullptr);
    189  ASSERT_EQ(SECSuccess, rv);
    190 
    191  // Test one past maximum length
    192  rv =
    193      PK11_PubEncrypt(pub_key.get(), CKM_RSA_PKCS, nullptr, ctxt.data(),
    194                      &ctxt_len, mod_len, msg.data(), max_msg_len + 1, nullptr);
    195  ASSERT_EQ(SECFailure, rv);
    196 
    197  // Make sure the the length will not overflow - i.e.
    198  // (padLen = modulusLen - (UINT_MAX + MINIMUM_PAD_LEN)) may overflow and
    199  // result in a value that appears valid.
    200  rv = PK11_PubEncrypt(pub_key.get(), CKM_RSA_PKCS, nullptr, ctxt.data(),
    201                       &ctxt_len, UINT_MAX, msg.data(), UINT_MAX, nullptr);
    202  ASSERT_EQ(SECFailure, rv);
    203 }
    204 }  // namespace nss_test