/*
 * Copyright (C) 2018 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#import "config.h"

#import <Security/SecAsn1Coder.h>
#import <Security/SecAsn1Templates.h>
#import <WebCore/LocalizedStrings.h>
#import <WebCore/SSLKeyGenerator.h>
#import <wtf/MainThread.h>
#import <wtf/Scope.h>
#import <wtf/URL.h>
#import <wtf/spi/cocoa/SecuritySPI.h>
#import <wtf/text/Base64.h>

#if USE(APPLE_INTERNAL_SDK)
#import <Security/SecKeyPriv.h>
#else
extern const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureMessagePKCS1v15MD5;
#endif

namespace TestWebKitAPI {

struct PublicKeyAndChallenge {
    SecAsn1PubKeyInfo subjectPublicKeyInfo;
    SecAsn1Item challenge;
};

struct SignedPublicKeyAndChallenge {
    PublicKeyAndChallenge publicKeyAndChallenge;
    SecAsn1AlgId algorithmIdentifier;
    SecAsn1Item signature;
};

const SecAsn1Template publicKeyAndChallengeTemplate[] {
    { SEC_ASN1_SEQUENCE, 0, nullptr, sizeof(PublicKeyAndChallenge) },
    { SEC_ASN1_INLINE, offsetof(PublicKeyAndChallenge, subjectPublicKeyInfo), kSecAsn1SubjectPublicKeyInfoTemplate, 0},
    { SEC_ASN1_INLINE, offsetof(PublicKeyAndChallenge, challenge), kSecAsn1IA5StringTemplate, 0 },
    { 0, 0, 0, 0}
};

const SecAsn1Template signedPublicKeyAndChallengeTemplate[] {
    { SEC_ASN1_SEQUENCE, 0, nullptr, sizeof(SignedPublicKeyAndChallenge) },
    { SEC_ASN1_INLINE, offsetof(SignedPublicKeyAndChallenge, publicKeyAndChallenge), publicKeyAndChallengeTemplate, 0 },
    { SEC_ASN1_INLINE, offsetof(SignedPublicKeyAndChallenge, algorithmIdentifier), kSecAsn1AlgorithmIDTemplate, 0 },
    { SEC_ASN1_BIT_STRING, offsetof(SignedPublicKeyAndChallenge, signature), 0, 0 },
    { 0, 0, 0, 0 }
};

const URL url { "http://www.webkit.org/"_str };

class SSLKeyGeneratorTest : public testing::Test {
public:
    virtual void SetUp()
    {
        WTF::initializeMainThread();
    }

    virtual void TearDown()
    {
        SecItemDelete((__bridge CFDictionaryRef) @{
            (id)kSecClass: (id)kSecClassKey,
            (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate,
            (id)kSecAttrLabel: WebCore::keygenKeychainItemName(url.host().toString()),
        });
        SecItemDelete((__bridge CFDictionaryRef) @{
            (id)kSecClass: (id)kSecClassKey,
            (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPublic,
            (id)kSecAttrLabel: WebCore::keygenKeychainItemName(url.host().toString()),
        });
    }
};

TEST_F(SSLKeyGeneratorTest, DefaultTest)
{
    constexpr auto challenge = "0123456789"_s;
    auto rawResult = WebCore::signedPublicKeyAndChallengeString(0, challenge, url);
    ASSERT_FALSE(rawResult.isEmpty());
    auto derResult = base64Decode(rawResult);
    ASSERT_TRUE(derResult);

    SecAsn1CoderRef coder = nullptr;
    ASSERT_EQ(errSecSuccess, SecAsn1CoderCreate(&coder));
    auto releaseCoder = makeScopeExit([&coder] {
        SecAsn1CoderRelease(coder);
    });

    SignedPublicKeyAndChallenge decodedResult { };
    SecAsn1Item derResultItem { derResult->size(), derResult->data() };
    ASSERT_EQ(errSecSuccess, SecAsn1DecodeData(coder, &derResultItem, signedPublicKeyAndChallengeTemplate, &decodedResult));

    // Check challenge
    EXPECT_FALSE(memcmp(challenge, decodedResult.publicKeyAndChallenge.challenge.Data, sizeof(challenge)));

    // Check signature
    RetainPtr<SecKeyRef> publicKey = nullptr;
    {
        NSDictionary* options = @{
            (id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA,
            (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPublic,
            (id)kSecAttrKeySizeInBits: @2048,
        };
        CFErrorRef errorRef = nullptr;
        publicKey = adoptCF(SecKeyCreateWithData(
            adoptCF(CFDataCreate(NULL, decodedResult.publicKeyAndChallenge.subjectPublicKeyInfo.subjectPublicKey.Data, decodedResult.publicKeyAndChallenge.subjectPublicKeyInfo.subjectPublicKey.Length)).get(),
            (__bridge CFDictionaryRef)options,
            &errorRef
        ));
        ASSERT_FALSE(errorRef);
    }

    SecAsn1Item dataToVerify { 0, nullptr };
    ASSERT_EQ(errSecSuccess, SecAsn1EncodeItem(coder, &decodedResult.publicKeyAndChallenge, publicKeyAndChallengeTemplate, &dataToVerify));

    // Signature's Length is in bits, we need it in bytes.
    EXPECT_TRUE(SecKeyVerifySignature(publicKey.get(), kSecKeyAlgorithmRSASignatureMessagePKCS1v15MD5, adoptCF(CFDataCreate(NULL, dataToVerify.Data, dataToVerify.Length)).get(), adoptCF(CFDataCreate(NULL, decodedResult.signature.Data, decodedResult.signature.Length / 8)).get(), NULL));

    // Check OIDs
    EXPECT_FALSE(memcmp(oidMd5Rsa.data, decodedResult.algorithmIdentifier.algorithm.Data, oidMd5Rsa.length));
    EXPECT_FALSE(memcmp(oidRsa.data, decodedResult.publicKeyAndChallenge.subjectPublicKeyInfo.algorithm.algorithm.Data, oidRsa.length));

}

} // namespace TestWebKitAPI
