Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8b7455ab authored by Chirag Pathak's avatar Chirag Pathak Committed by David Zeuthen
Browse files

Add support and VTS test for RSA OAEP MGF1.

Test: atest VtsAidlKeyMintV1_0TargetTest
Bug: 160968519
Change-Id: I7093b26217b69ea36b4be8837b42cb9446887685
parent 2528ddca
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -94,6 +94,8 @@ enum ErrorCode {
  ATTESTATION_IDS_NOT_PROVISIONED = -75,
  INVALID_OPERATION = -76,
  STORAGE_KEY_UNSUPPORTED = -77,
  INCOMPATIBLE_MGF_DIGEST = -78,
  UNSUPPORTED_MGF_DIGEST = -79,
  UNIMPLEMENTED = -100,
  VERSION_MISMATCH = -101,
  UNKNOWN_ERROR = -1000,
+1 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ enum Tag {
  EC_CURVE = 268435466,
  RSA_PUBLIC_EXPONENT = 1342177480,
  INCLUDE_UNIQUE_ID = 1879048394,
  RSA_OAEP_MGF_DIGEST = 536871115,
  BLOB_USAGE_REQUIREMENTS = 268435757,
  BOOTLOADER_ONLY = 1879048494,
  ROLLBACK_RESISTANCE = 1879048495,
+2 −0
Original line number Diff line number Diff line
@@ -99,6 +99,8 @@ enum ErrorCode {
    ATTESTATION_IDS_NOT_PROVISIONED = -75,
    INVALID_OPERATION = -76,
    STORAGE_KEY_UNSUPPORTED = -77,
    INCOMPATIBLE_MGF_DIGEST = -78,
    UNSUPPORTED_MGF_DIGEST = -79,

    UNIMPLEMENTED = -100,
    VERSION_MISMATCH = -101,
+16 −0
Original line number Diff line number Diff line
@@ -187,6 +187,22 @@ enum Tag {
     */
    INCLUDE_UNIQUE_ID = (7 << 28) /* TagType:BOOL */ | 202,

     /**
      * Tag::RSA_OAEP_MGF_DIGEST specifies the MGF1 digest algorithms that may be used with
      * RSA encryption/decryption with OAEP padding. If the key characteristics supports OAEP
      * and this tag is absent then SHA1 digest is selected by default for MGF1.
      *
      * This tag is repeatable for key generation/import.  If this tag is present in the key
      * characteristics with one or more values from @4.0::Digest, then for RSA cipher
      * operations with OAEP Padding, the caller must specify a digest in the additionalParams
      * argument of begin operation. If this tag is missing or the specified digest is not in
      * the digests associated with the key then begin operation must fail with
      * ErrorCode::INCOMPATIBLE_MGF_DIGEST.
      *
      * Must be hardware-enforced.
      */
     RSA_OAEP_MGF_DIGEST = (2 << 28) /* TagType:ENUM_REP */ | 203,

    /**
     * TODO(seleneh) this tag needs to be deleted from all codes.
     *
+101 −0
Original line number Diff line number Diff line
@@ -2055,6 +2055,107 @@ TEST_P(EncryptionOperationsTest, RsaOaepTooLarge) {
    EXPECT_EQ(0U, result.size());
}

/*
 * EncryptionOperationsTest.RsaOaepWithMGFDigestSuccess
 *
 * Verifies that RSA-OAEP encryption operations work, with all SHA 256 digests and all type of MGF1
 * digests.
 */
TEST_P(EncryptionOperationsTest, RsaOaepWithMGFDigestSuccess) {
    auto digests = ValidDigests(false /* withNone */, true /* withMD5 */);

    size_t key_size = 2048;  // Need largish key for SHA-512 test.
    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                                 .OaepMGFDigest(digests)
                                                 .Authorization(TAG_NO_AUTH_REQUIRED)
                                                 .RsaEncryptionKey(key_size, 65537)
                                                 .Padding(PaddingMode::RSA_OAEP)
                                                 .Digest(Digest::SHA_2_256)));

    string message = "Hello";

    for (auto digest : digests) {
        auto params = AuthorizationSetBuilder()
                              .Authorization(TAG_RSA_OAEP_MGF_DIGEST, digest)
                              .Digest(Digest::SHA_2_256)
                              .Padding(PaddingMode::RSA_OAEP);
        string ciphertext1 = EncryptMessage(message, params);
        if (HasNonfatalFailure()) std::cout << "-->" << digest << std::endl;
        EXPECT_EQ(key_size / 8, ciphertext1.size());

        string ciphertext2 = EncryptMessage(message, params);
        EXPECT_EQ(key_size / 8, ciphertext2.size());

        // OAEP randomizes padding so every result should be different (with astronomically high
        // probability).
        EXPECT_NE(ciphertext1, ciphertext2);

        string plaintext1 = DecryptMessage(ciphertext1, params);
        EXPECT_EQ(message, plaintext1) << "RSA-OAEP failed with digest " << digest;
        string plaintext2 = DecryptMessage(ciphertext2, params);
        EXPECT_EQ(message, plaintext2) << "RSA-OAEP failed with digest " << digest;

        // Decrypting corrupted ciphertext should fail.
        size_t offset_to_corrupt = random() % ciphertext1.size();
        char corrupt_byte;
        do {
            corrupt_byte = static_cast<char>(random() % 256);
        } while (corrupt_byte == ciphertext1[offset_to_corrupt]);
        ciphertext1[offset_to_corrupt] = corrupt_byte;

        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params));
        string result;
        EXPECT_EQ(ErrorCode::UNKNOWN_ERROR, Finish(ciphertext1, &result));
        EXPECT_EQ(0U, result.size());
    }
}

/*
 * EncryptionOperationsTest.RsaOaepWithMGFIncompatibleDigest
 *
 * Verifies that RSA-OAEP encryption operations fail in the correct way when asked to operate
 * with incompatible MGF digest.
 */
TEST_P(EncryptionOperationsTest, RsaOaepWithMGFIncompatibleDigest) {
    ASSERT_EQ(ErrorCode::OK,
              GenerateKey(AuthorizationSetBuilder()
                                  .Authorization(TAG_RSA_OAEP_MGF_DIGEST, Digest::SHA_2_256)
                                  .Authorization(TAG_NO_AUTH_REQUIRED)
                                  .RsaEncryptionKey(2048, 65537)
                                  .Padding(PaddingMode::RSA_OAEP)
                                  .Digest(Digest::SHA_2_256)));
    string message = "Hello World!";

    auto params = AuthorizationSetBuilder()
                          .Padding(PaddingMode::RSA_OAEP)
                          .Digest(Digest::SHA_2_256)
                          .Authorization(TAG_RSA_OAEP_MGF_DIGEST, Digest::SHA_2_224);
    EXPECT_EQ(ErrorCode::INCOMPATIBLE_MGF_DIGEST, Begin(KeyPurpose::ENCRYPT, params));
}

/*
 * EncryptionOperationsTest.RsaOaepWithMGFUnsupportedDigest
 *
 * Verifies that RSA-OAEP encryption operations fail in the correct way when asked to operate
 * with unsupported MGF digest.
 */
TEST_P(EncryptionOperationsTest, RsaOaepWithMGFUnsupportedDigest) {
    ASSERT_EQ(ErrorCode::OK,
              GenerateKey(AuthorizationSetBuilder()
                                  .Authorization(TAG_RSA_OAEP_MGF_DIGEST, Digest::SHA_2_256)
                                  .Authorization(TAG_NO_AUTH_REQUIRED)
                                  .RsaEncryptionKey(2048, 65537)
                                  .Padding(PaddingMode::RSA_OAEP)
                                  .Digest(Digest::SHA_2_256)));
    string message = "Hello World!";

    auto params = AuthorizationSetBuilder()
                          .Padding(PaddingMode::RSA_OAEP)
                          .Digest(Digest::SHA_2_256)
                          .Authorization(TAG_RSA_OAEP_MGF_DIGEST, Digest::NONE);
    EXPECT_EQ(ErrorCode::UNSUPPORTED_MGF_DIGEST, Begin(KeyPurpose::ENCRYPT, params));
}

/*
 * EncryptionOperationsTest.RsaPkcs1Success
 *
Loading