/*
 * Copyright (C) 2020 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.
 */

#pragma once

#if ENABLE(WEB_RTC)

#include "ExceptionOr.h"
#include "RTCRtpTransformBackend.h"
#include <wtf/Lock.h>
#include <wtf/ThreadSafeRefCounted.h>

namespace WebCore {

class CryptoKey;

class RTCRtpSFrameTransformer : public ThreadSafeRefCounted<RTCRtpSFrameTransformer, WTF::DestructionThread::Main> {
public:
    enum class CompatibilityMode { None, H264, VP8 };

    WEBCORE_EXPORT static Ref<RTCRtpSFrameTransformer> create(CompatibilityMode = CompatibilityMode::None);
    WEBCORE_EXPORT ~RTCRtpSFrameTransformer();

    void setIsEncrypting(bool);
    void setAuthenticationSize(uint64_t);
    void setMediaType(RTCRtpTransformBackend::MediaType);

    WEBCORE_EXPORT ExceptionOr<void> setEncryptionKey(const Vector<uint8_t>& rawKey, std::optional<uint64_t>);

    enum class Error { KeyID, Authentication, Syntax, Other };
    struct ErrorInformation {
        Error error;
        String message;
        uint64_t keyId { 0 };
    };
    using TransformResult = Expected<Vector<uint8_t>, ErrorInformation>;
    WEBCORE_EXPORT TransformResult transform(Span<const uint8_t>);

    const Vector<uint8_t>& authenticationKey() const { return m_authenticationKey; }
    const Vector<uint8_t>& encryptionKey() const { return m_encryptionKey; }
    const Vector<uint8_t>& saltKey() const { return m_saltKey; }

    uint64_t keyId() const { return m_keyId; }
    uint64_t counter() const { return m_counter; }
    void setCounter(uint64_t counter) { m_counter = counter; }

    bool hasKey(uint64_t) const;

private:
    WEBCORE_EXPORT explicit RTCRtpSFrameTransformer(CompatibilityMode);

    TransformResult decryptFrame(Span<const uint8_t>);
    TransformResult encryptFrame(Span<const uint8_t>);

    enum class ShouldUpdateKeys { No, Yes };
    ExceptionOr<void> updateEncryptionKey(const Vector<uint8_t>& rawKey, std::optional<uint64_t>, ShouldUpdateKeys = ShouldUpdateKeys::Yes) WTF_REQUIRES_LOCK(m_keyLock);

    ExceptionOr<Vector<uint8_t>> computeSaltKey(const Vector<uint8_t>&);
    ExceptionOr<Vector<uint8_t>> computeAuthenticationKey(const Vector<uint8_t>&);
    ExceptionOr<Vector<uint8_t>> computeEncryptionKey(const Vector<uint8_t>&);

    ExceptionOr<Vector<uint8_t>> encryptData(const uint8_t*, size_t, const Vector<uint8_t>& iv, const Vector<uint8_t>& key);
    ExceptionOr<Vector<uint8_t>> decryptData(const uint8_t*, size_t, const Vector<uint8_t>& iv, const Vector<uint8_t>& key);
    Vector<uint8_t> computeEncryptedDataSignature(const Vector<uint8_t>& nonce, const uint8_t* header, size_t headerSize, const uint8_t* data, size_t dataSize, const Vector<uint8_t>& key);
    void updateAuthenticationSize();

    mutable Lock m_keyLock;
    bool m_hasKey { false };
    Vector<uint8_t> m_authenticationKey;
    Vector<uint8_t> m_encryptionKey;
    Vector<uint8_t> m_saltKey;

    struct IdentifiedKey {
        uint64_t keyId { 0 };
        Vector<uint8_t> keyData;
    };
    Vector<IdentifiedKey> m_keys WTF_GUARDED_BY_LOCK(m_keyLock);

    bool m_isEncrypting { false };
    uint64_t m_authenticationSize { 10 };
    uint64_t m_keyId { 0 };
    uint64_t m_counter { 0 };
    CompatibilityMode m_compatibilityMode { CompatibilityMode::None };
};

inline void RTCRtpSFrameTransformer::setIsEncrypting(bool isEncrypting)
{
    m_isEncrypting = isEncrypting;
}

inline void RTCRtpSFrameTransformer::setAuthenticationSize(uint64_t size)
{
    m_authenticationSize = size;
}

inline void RTCRtpSFrameTransformer::setMediaType(RTCRtpTransformBackend::MediaType mediaType)
{
    if (mediaType == RTCRtpTransformBackend::MediaType::Video) {
        m_authenticationSize = 10;
        return;
    }
    m_authenticationSize = 4;
    m_compatibilityMode = CompatibilityMode::None;
}

} // namespace WebCore

#endif // ENABLE(WEB_RTC)
