// 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 "gtest/gtest.h"

#include <stdint.h>
#include <memory>

#include "blapi.h"
#include "secitem.h"

template <class T>
struct ScopedDelete {
  void operator()(T* ptr) {
    if (ptr) {
      PORT_FreeArena(ptr->arena, PR_TRUE);
    }
  }
};

typedef std::unique_ptr<RSAPrivateKey, ScopedDelete<RSAPrivateKey>>
    ScopedRSAPrivateKey;

class RSATest : public ::testing::Test {
 protected:
  RSAPrivateKey* CreateKeyWithExponent(int keySizeInBits,
                                       unsigned char publicExponent) {
    SECItem exp = {siBuffer, 0, 0};
    unsigned char pubExp[1] = {publicExponent};
    exp.data = pubExp;
    exp.len = 1;

    return RSA_NewKey(keySizeInBits, &exp);
  }
};

TEST_F(RSATest, expOneTest) {
  ScopedRSAPrivateKey key(CreateKeyWithExponent(2048, 0x01));
  ASSERT_TRUE(key == nullptr);
}
TEST_F(RSATest, expTwoTest) {
  ScopedRSAPrivateKey key(CreateKeyWithExponent(2048, 0x02));
  ASSERT_TRUE(key == nullptr);
}
TEST_F(RSATest, expFourTest) {
  ScopedRSAPrivateKey key(CreateKeyWithExponent(2048, 0x04));
  ASSERT_TRUE(key == nullptr);
}
TEST_F(RSATest, WrongKeysizeTest) {
  ScopedRSAPrivateKey key(CreateKeyWithExponent(2047, 0x03));
  ASSERT_TRUE(key == nullptr);
}

TEST_F(RSATest, expThreeTest) {
  ScopedRSAPrivateKey key(CreateKeyWithExponent(2048, 0x03));
#ifdef NSS_FIPS_DISABLED
  ASSERT_TRUE(key != nullptr);
#else
  ASSERT_TRUE(key == nullptr);
#endif
}

TEST_F(RSATest, DecryptBlockTestErrors) {
  unsigned char pubExp[3] = {0x01, 0x00, 0x01};
  SECItem exp = {siBuffer, pubExp, 3};
  ScopedRSAPrivateKey key(RSA_NewKey(2048, &exp));
  ASSERT_TRUE(key);
  uint8_t out[10] = {0};
  uint8_t in_small[100] = {0};
  unsigned int outputLen = 0;
  unsigned int maxOutputLen = sizeof(out);

  // This should fail because input the same size as the modulus (256).
  SECStatus rv = RSA_DecryptBlock(key.get(), out, &outputLen, maxOutputLen,
                                  in_small, sizeof(in_small));
  EXPECT_EQ(SECFailure, rv);

  uint8_t in[256] = {0};
  // This should fail because the padding checks will fail,
  // however, mitigations for Bleichenbacher attacks transform failures
  // to a different output.
  rv = RSA_DecryptBlock(key.get(), out, &outputLen, maxOutputLen, in,
                        sizeof(in));
  EXPECT_EQ(SECSuccess, rv);
  // outputLen should <= 256-11=245.
  EXPECT_LE(outputLen, 245u);

  // This should fail because the padding checks will fail,
  // however, mitigations for Bleichenbacher attacks transform failures
  // to a different output.
  uint8_t out_long[260] = {0};
  maxOutputLen = sizeof(out_long);
  rv = RSA_DecryptBlock(key.get(), out_long, &outputLen, maxOutputLen, in,
                        sizeof(in));
  EXPECT_EQ(SECSuccess, rv);
  // outputLen should <= 256-11=245.
  EXPECT_LE(outputLen, 245u);
  // Everything over 256 must be 0 in the output.
  uint8_t out_long_test[4] = {0};
  EXPECT_EQ(0, memcmp(out_long_test, &out_long[256], 4));
}
