#include <gtest/gtest.h>

#include "AndroidCertificate.h"
#include "JarCertificate.h"
#include "NativeCertificate.h"
#include "Pkcs7.h"
#include "PrivateKey.h"
#include "PublicKey.h"
#include "ProcessCertificate.h"
#include "Utils.h"

using namespace std;

static const string kRootPrivateKey = "-----BEGIN PRIVATE KEY-----\n"
    "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDcUnHlq/vIpnJb\n"
    "2QajRvTL18O7feuSrWznJvEjSa4Xqlm+HFsXkX/WJiLgIHdMczoqx3cQssmG0cSa\n"
    "CKETmt1dM21tkQ0sZUaMs6QVYPlTvjryCnmd3W59CJH3a5UJ/BmpG6uL40a34/ig\n"
    "f5jKS9fAfBD23+athxn/V1ntJzPVQ8fHS13mQUjqAj4Y+ABVBOSVAR87XlNhmiSy\n"
    "Sqxb2EwRUVEKzkOvy/KCR86bf48yFft6ywgKwp33ya5ZJ9Q3CbEdy2s05HzCFTyR\n"
    "WMmILz+5ijgX8A8nwaGfu8TxzyHO5KVeuyRHovh5iezetaHO40kojWvdSB5veA7/\n"
    "UuaU/FmNAgMBAAECggEBANpLfbpYKwJlmI1UfPUuCsIlqDOO0efkmTB2LxoNmMat\n"
    "7Hkm00KI0Sa3Znq28Dz5NjrIozoSSwaftLIBtscb/BSqLdQPkgPY3IvwObVM/fxx\n"
    "USocIt+9VAnige2p1GOuOyaI2fGiYKE26VLs2dAmUUDQLGbO9VodsC6Et/73hq3X\n"
    "wVWW2QRvb3pxquQOZlWufQqUWrG4BbsA9wuekmN5wgBc1Zpb8kGR2X4zr6Upu6Lf\n"
    "OG0oPVdS38e0dXeFIwCncNCnMIgRxDTImJVsKnMxPBoNNsaR584jEdixEtoRFUpG\n"
    "ocRnH6rnuHSuwm3V8ANyjxqJMK6qoJ8Us/ErLNsKPSkCgYEA+bFRf14Wof2ZEgYw\n"
    "o5U1B0vvcJAtrau/W4WDnz0U8C5eTjfw5XQQGveIT/dR5pAA2i7MOLBnKoqB7kNd\n"
    "k2NevBejIwzv6fpxGh7ZtDf1nl7AE8e/8mUsp0CWoccOniwBZyzhHRJ16l7TyOjX\n"
    "zfA7s9aV6of1UbBB1LD1GoqCl58CgYEA4eMyRpGIOQwmqlf80hGdZ+f596CvOetZ\n"
    "5AVSp2WBkbNgTd4kVoINF4szYU5YcG9S6UfkfvnIIeT4+as5DNmmlUTjy+yOmLMC\n"
    "0byuyZ7e4qsXqchDzK46PQIVYI/8o6raDIgHysD8cGuA6a44/GKLJ+uchCYWaXQC\n"
    "Dpm339bRL1MCgYEArFAFKPuabOIgv4KMEGfIt6dcrvagv0hV/2ftRHgXugSVyi7q\n"
    "zL5C2wlWBbFs0Msx+1/uSXTbTU1Wi0HsEumxl+ZMC8VCz9qoMNl3bdpsY4WJ0ly4\n"
    "ByRxI178VNqVKOy/bx9WnwR9YWddijm9q/4MhXgh7z8yOdSEKa6RB2bs5osCgYEA\n"
    "xqCdaOg3vNIufcN5EM9kdiXJ7DFjY67MEHGNyJy9Xn04xb/8fAVHtdg1ie72XYfG\n"
    "hFMvXWgOz58kP4aMV/xbOw6ksICGs0dVx0/+8lO88dw4ppbu52Cc3WCjo5F5OgHW\n"
    "Uwaas3MXh1NAvDry6RtN+gB4VMuZEYls9aG9yhp/PvkCgYA3kJEDlMXBMbF26SrO\n"
    "J7e5C3Yl8J965gFx2oiOdtLaL/cmT8eAH3xJ6Lqxf6CBEbNznp+SV3XXfX61pB9n\n"
    "CaZ2JeA9+hFia6vFTao3PoeUHawvbqQmqZkq02E094yRktLdqFxz7BoKVk4cXJGe\n"
    "WRwrtGOfH6YtOLuCFCdSF21vZQ==\n"
    "-----END PRIVATE KEY-----";

static const string kRootPublicKey = "-----BEGIN PUBLIC KEY-----\n"
    "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3FJx5av7yKZyW9kGo0b0\n"
    "y9fDu33rkq1s5ybxI0muF6pZvhxbF5F/1iYi4CB3THM6Ksd3ELLJhtHEmgihE5rd\n"
    "XTNtbZENLGVGjLOkFWD5U7468gp5nd1ufQiR92uVCfwZqRuri+NGt+P4oH+YykvX\n"
    "wHwQ9t/mrYcZ/1dZ7Scz1UPHx0td5kFI6gI+GPgAVQTklQEfO15TYZokskqsW9hM\n"
    "EVFRCs5Dr8vygkfOm3+PMhX7essICsKd98muWSfUNwmxHctrNOR8whU8kVjJiC8/\n"
    "uYo4F/APJ8Ghn7vE8c8hzuSlXrskR6L4eYns3rWhzuNJKI1r3Ugeb3gO/1LmlPxZ\n"
    "jQIDAQAB\n"
    "-----END PUBLIC KEY-----";

static const string kPath = "/system/bin/xattr_manager";
static const string kFiveSignature =
    "AwICoMVPjACAbFcS4dIQ5XKj4SHfC2SSQNJdNTpPudmm4klhKgfeklV2O42iehaG"
    "kpw2I3U/PL1JL+jwwMkleewd41zlvn1l0TZQ4YNcjXfDwSotEku16n1mF3oPjNkG"
    "sbFuFcY24r1ME5C6GLJV2BhKBUlMQc9nTbPSoBa+syKJgr3+2vSFVYw=";

static const string kExpectedNativeRequest =
    "MGgCAQECAQACAQAEIMYcetgcChobO3Tj9+kQBxNkBTQYaazIPdcgG/o8SQbPBBkv"
    "c3lzdGVtL2Jpbi94YXR0cl9tYW5hZ2VyBCAAEBEZzUPDbFxQv/q1Iq3zaA1t+sEs"
    "gkYSqso6TRVOmg==";

static const string kNativeRequestSignature =
    "q1sBkonDw6G9TnBdJSnkjxMHxdwKpkRaXVzIOeVrLPlRFjT9yTzYSgN4OPbcuvk4"
    "m0d9wrg5B/+yVHa9yPo+mL/3Y1ywyr8zALBwvm6fbt58gIA2cQhJl9y/Q7g0J5Ev"
    "ODGyIQIJMThKNPqsCvlFTZ2eITCXhPCQcvfkDk3H2wn2R9sK5kg8+eqFKCmOwtmf"
    "6FQ0Z3r6PNkJlFWTAa/gr5priPoA3uFFU9VKoe4ZDbqIUWa0DNTXR1c5SqHGp8P0"
    "hJLsfABNOLxJSUeOifor4XLb5bk7ZDr3w3dGNQvbfbEPxnIaRH36inbVf1QeKEh3"
    "ZqEk1tTvnJ/EQvTuS3MhtA==";

static const string kExpectedPaCertificate =
    "MIIBbjBoAgEBAgEAAgEABCDGHHrYHAoaGzt04/fpEAcTZAU0GGmsyD3XIBv6PEkG"
    "zwQZL3N5c3RlbS9iaW4veGF0dHJfbWFuYWdlcgQgABARGc1Dw2xcUL/6tSKt82gN"
    "bfrBLIJGEqrKOk0VTpoEggEAq1sBkonDw6G9TnBdJSnkjxMHxdwKpkRaXVzIOeVr"
    "LPlRFjT9yTzYSgN4OPbcuvk4m0d9wrg5B/+yVHa9yPo+mL/3Y1ywyr8zALBwvm6f"
    "bt58gIA2cQhJl9y/Q7g0J5EvODGyIQIJMThKNPqsCvlFTZ2eITCXhPCQcvfkDk3H"
    "2wn2R9sK5kg8+eqFKCmOwtmf6FQ0Z3r6PNkJlFWTAa/gr5priPoA3uFFU9VKoe4Z"
    "DbqIUWa0DNTXR1c5SqHGp8P0hJLsfABNOLxJSUeOifor4XLb5bk7ZDr3w3dGNQvb"
    "fbEPxnIaRH36inbVf1QeKEh3ZqEk1tTvnJ/EQvTuS3MhtA==";

static const string kAndroidPackageName =
    "com.sec.android.secureclient";

static const string kAndroidRsaCertificate =
    "MIIErwYJKoZIhvcNAQcCoIIEoDCCBJwCAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3"
    "DQEHAaCCAxEwggMNMIIB9aADAgECAgRQAEm6MA0GCSqGSIb3DQEBCwUAMDcxCzAJ"
    "BgNVBAYTAlVTMRAwDgYDVQQKEwdBbmRyb2lkMRYwFAYDVQQDEw1BbmRyb2lkIERl"
    "YnVnMB4XDTE0MDIwNTEyMzUwMFoXDTQ0MDEyOTEyMzUwMFowNzELMAkGA1UEBhMC"
    "VVMxEDAOBgNVBAoTB0FuZHJvaWQxFjAUBgNVBAMTDUFuZHJvaWQgRGVidWcwggEi"
    "MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDLSx5d6+jeuwfVRJxfu/UrRDLl"
    "3tT6MlCLircJzg4ZXg9CHsWamGSZ+VMO78u+KXkvm/3eXnsYGIK8ahj5pLt/RQQ8"
    "0g3i9uT2gxJ5xg0P1Xk7RCS0djyeiG1rju+zNnTBodZytl/duDZlwYtaydrjoQYZ"
    "rCHBSPJqFy2ybAp4iIMX0Tytaz2cgFCKAS7FazPoR11qz/F05/AoVeeg57thgNva"
    "M8VrIcEWgrErrQ4+I8rPcr3Fg6AOVCvZ3L3KR3A+P/9JLxfjpE4e9R2e1rMHWu8q"
    "JS4J+tuIYipFQMn1B5mtpVBQZht4ktzPoU008m9ssoK1YTC1l6DGKrrm/qZPAgMB"
    "AAGjITAfMB0GA1UdDgQWBBSqx9bkuGWlThei7vyFjnZqdmTJrjANBgkqhkiG9w0B"
    "AQsFAAOCAQEARNksJE7z1VWIr4C2p5GP7V37SWAXHpd1DZV1VW2qYpTL7FAivKXV"
    "fa0d/AQh8hALCA7dPWLCDbJ5T9IadzssWyKwfJOdYhDwaKjy5XtNZsqheQcb2+xy"
    "csrAqR1Q8mUU0QcuLJTfM/4QpFZND/J1Vl7ZLFWWKZ5uawfnXtoDNu87KwnQKrWr"
    "aDGXniI2VPti5FPmtHPAgzuXCD9fMmq58W9eVTItSWRbHXxomj9+0v4cJJXMc4TC"
    "/s2LybXv6hhCQ3I2kuPlyZO5NsuPHYGKm9KqQZ9E+gotEr1QmrqdKguOcLvPKKQQ"
    "z8gEQlpfCkoECLPH3R2E8RlPYqrKExi7tTGCAWYwggFiAgEBMD8wNzELMAkGA1UE"
    "BhMCVVMxEDAOBgNVBAoTB0FuZHJvaWQxFjAUBgNVBAMTDUFuZHJvaWQgRGVidWcC"
    "BFAASbowCQYFKw4DAhoFADANBgkqhkiG9w0BAQEFAASCAQBAGTEUba62bNfqs5o/"
    "FNEn4nZ1zICSuGcqPgltmTvEG4rGpt3j+JJqNreZukDGdrXus52RqR7en+YbWBp4"
    "2yY8qDEzdG7c/Znaf+cxuTNrk/BjtXbqZ8jz/yS1dPawFMoj6f/piveQC2mBtVoy"
    "JAfL9uzLqUIm/SRZ7ddHEcmE9GfZZVXUaHuFJUyHdQV9aFaGYym/Fdr8gQtCxMxt"
    "umH1US6c/K1Wz58B8NrIiEoYluXTKkgq6ODdkCfeld5Z+0M+5BB2vqMjQ3gM4qqT"
    "DwJYrmCMfgS2L/9NyQf81mxQ2+Lmdi4k7lu4gF6q4FCoh8BlucZpKGzL0qp5kT9C"
    "7Sc9";

static const string kAndroidFiveSignature =
    "BQKAAMtLHl3r6N67B9VEnF+79StEMuXe1PoyUIuKtwnODhleD0IexZqYZJn5Uw7v"
    "y74peS+b/d5eexgYgrxqGPmku39FBDzSDeL25PaDEnnGDQ/VeTtEJLR2PJ6IbWuO"
    "77M2dMGh1nK2X924NmXBi1rJ2uOhBhmsIcFI8moXLbJsCniIYwgd1Vk9HfqyfXVg"
    "a9SccLwHpXmAfCUG8wX6derk13p7yfBsvXQVOA==";

static const string kExpectedAndroidPaCertificate =
    "MIIBcTBrAgEBAgEBAgEABCBqqRVjYJt8e5STZ+Inekw1YPIDZrK+aGSokiFwC2pl"
    "OQQcY29tLnNlYy5hbmRyb2lkLnNlY3VyZWNsaWVudAQgo4kYoNQusv57ddyBSjuV"
    "cexRYyZlAL8vLT1zDrFBjZYEggEASr6/CAXw17b+AGLSRaIi56Rql1bIDy4cBtaW"
    "0gyXnRuGRtEGDvfeQr9gh/qSkLKIx/HYBzZJZV5TI8w03jITCFDU3tfYVCC7VtqA"
    "Vp8R/nOh1vPrZv4UZLtqzeDY2kV2A7knt4kuFk/d85VoVjgMUZktF/QEDO6SWGGU"
    "e4t+cKttwr1TL+VDTiB61o7sV0dJJvmMOBKbHL0xZsMi0NrH0i9GdGkRWyeSzMFi"
    "idFIRvY1zo3FwpQG/YPH4nAQCdzN5p4ligFt/5rY1LQW+ABUizQp8PUH+80IYKjO"
    "QrVwyJPAtN6+6UxmXDFR3n+z6xOXG7ZW3EJodt3AOEv7adD7Zw==";

static const string kJarPath = "/system/framework/services.jar";

static const string kExpectedJarPaCertificate =
    "MIIBczBtAgEBAgEBAgEABCDtwRnRFs0Yi94I+B1+o4bimNOjOfCkeXkkYTbiS1Hj"
    "2gQeL3N5c3RlbS9mcmFtZXdvcmsvc2VydmljZXMuamFyBCAAEBEZzUPDbFxQv/q1"
    "Iq3zaA1t+sEsgkYSqso6TRVOmgSCAQDC89SJU1bSOc0Pqa8XBmkzqaKFhUPkUoz8"
    "Fh06kpAOW06Pt9n+8bumzJB1kHA2lbT15f0wnLa2byUMRAQz68NjOfL0xgJSrVga"
    "8jCUzNFahrq3gWldcLdX+jovJlPDwnZnmljwO7dQG9qfGEvdUwO0aYdj5IxLW9xB"
    "xwPPwxFTDmq+v5VW/b0kSSH/EAmYkTAZ+is6dow7Vwl2rMuyOk/Ch/gvt1pLUQrn"
    "QKuRL0+l/V6ZqmZ6e2RFNptjL5Y1MQMdCNmW7IeXkZOL/wmc0FoMhlQtxxp6BK2i"
    "55REXifhX+Ei9CTMbDOvlG/u6YrWXx8DxYxoR0ODlvVj+ODoX4n8";

TEST(PaSignerTest, PaNativeCertificateTest) {
  PrivateKey pa_root_private_key(StringToVector(kRootPrivateKey));
  NativeCertificate certificate(kPath, kFiveSignature, 0);

  certificate.Sign(pa_root_private_key);

  ASSERT_EQ(kExpectedPaCertificate, certificate.ToAsn1Buffer());
}

TEST(PaSignerTest, PaAndroidCertificateTest) {
  PrivateKey pa_root_private_key(StringToVector(kRootPrivateKey));

  Pkcs7 package_public_key(Base64Decode(kAndroidRsaCertificate));

  AndroidCertificate certificate(kAndroidPackageName, package_public_key,
      kAndroidFiveSignature, 0);

  certificate.Sign(pa_root_private_key);

  ASSERT_EQ(kExpectedAndroidPaCertificate, certificate.ToAsn1Buffer());
}

TEST(PaSignerTest, PaNativeCertificateVerifyByPrivateTest) {
  PrivateKey pa_root_private_key(StringToVector(kRootPrivateKey));
  NativeCertificate certificate(kPath, kFiveSignature, 0);

  certificate.Sign(pa_root_private_key);

  ASSERT_TRUE(certificate.Verify(pa_root_private_key));
}

TEST(PaSignerTest, PaNativeCertificateVerifyByPublicTest) {
  PrivateKey pa_root_private_key(StringToVector(kRootPrivateKey));
  NativeCertificate certificate(kPath, kFiveSignature, 0);

  certificate.Sign(pa_root_private_key);

  PublicKey public_key(StringToVector(kRootPublicKey));

  ASSERT_TRUE(certificate.Verify(public_key));
}

TEST(PaSignerTest, PaNativeCertificateEncodedTest) {
  PrivateKey pa_root_private_key(StringToVector(kRootPrivateKey));
  NativeCertificate certificate(kPath, kFiveSignature, 0);

  certificate.Sign(pa_root_private_key);

  ProcessCertificate certificate2(certificate.ToAsn1Buffer());

  ASSERT_TRUE(certificate2.Verify(pa_root_private_key));
}

TEST(PaSignerTest, PaNativeCertificateRequestTest) {
  PrivateKey pa_root_private_key(StringToVector(kRootPrivateKey));
  NativeCertificate certificate(kPath, kFiveSignature, 0);

  ASSERT_EQ(kExpectedNativeRequest, certificate.GetRequest());
}

TEST(PaSignerTest, PaNativeCertificateRequestSignatureTest) {
  ProcessCertificate certificate(kExpectedNativeRequest,
                                 kNativeRequestSignature);

  PublicKey public_key(StringToVector(kRootPublicKey));

  ASSERT_TRUE(certificate.Verify(public_key));
}

TEST(PaSignerTest, PaJarCertificateTest) {
  PrivateKey pa_root_private_key(StringToVector(kRootPrivateKey));
  JarCertificate certificate(kJarPath, kFiveSignature, 0);

  certificate.Sign(pa_root_private_key);

  ASSERT_EQ(kExpectedJarPaCertificate, certificate.ToAsn1Buffer());
}
