/*
 *
 *    Copyright (c) 2013-2017 Nest Labs, Inc.
 *    All rights reserved.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

import com.nestlabs.weave.security.ApplicationKeySupport;
import com.nestlabs.weave.security.WeaveKeyId;

public final class ApplicationKeySupportTest extends SimpleTest
{
    public static void main(String[] args)
    {
        ApplicationKeySupportTest testObj = new ApplicationKeySupportTest();
        
        int res = testObj.runTests(new String[] {
            "TestAppStaticKeyDerivation",
            "TestAppRotatingKeyDerivation",
        });
        
        System.exit(res);
    }
    
    public void TestAppStaticKeyDerivation() throws Exception
    {
        TestKeySource keySource = new TestKeySource();
        
        int keyId = WeaveKeyId.makeAppStaticKeyId(WeaveKeyId.ClientRootKey, WeaveKeyId.makeAppGroupMasterKeyId(10));

        byte[] diversifier = toByteArray(new int[]
            {
                0x74, 0x98, 0x57, 0xFB, 0x21, 0xDB, 0x2B, 0x28, 0x4D, 0x8D, 0x40
            });
        
        byte[] expectedDerivedKey = toByteArray(new int[]
            {
                0x68, 0xBB, 0x09, 0xA5, 0x04, 0x76, 0x1D, 0x68, 0x07, 0x78, 0xC7, 0xF8, 0x34, 0xA6, 0x71, 0x0E, 
                0x7E, 0xA4, 0x89, 0x8F, 0x4D, 0x1D, 0xE5, 0x03, 0x64, 0xBA, 0xB4, 0xD7, 0x19, 0x76, 0xD8, 0x1B, 
                0x0D, 0x29, 0xA4, 0xA6, 0x04, 0x3C, 0xF1, 0x87, 0xDD, 0x96, 0x55, 0x09, 0x6B, 0x64, 0x49, 0x70, 
            });

        byte[] derivedKey = ApplicationKeySupport.deriveApplicationKey(keyId, keySource, null, diversifier, expectedDerivedKey.length);
        
        assertEqual(derivedKey, expectedDerivedKey, "Derived key");
    }
    
    public void TestAppRotatingKeyDerivation() throws Exception
    {
        TestKeySource keySource = new TestKeySource();

        int keyId = WeaveKeyId.makeAppRotatingKeyId(WeaveKeyId.ServiceRootKey, WeaveKeyId.makeEpochKeyId(3), WeaveKeyId.makeAppGroupMasterKeyId(54), false);

        byte[] diversifier = toByteArray(new int[]
            {
                0x74, 0x98, 0x57, 0xFB, 0x21, 0xDB, 0x2B, 0x28, 0x4D, 0x8D, 0x40, 0x45, 0x46, 0x47, 0x48, 0x49
            });
        
        byte[] expectedDerivedKey = toByteArray(new int[]
            {
                0x9B, 0x80, 0xEF, 0xFB, 0x6A, 0xC6, 0x94, 0xBD, 0xB8, 0xF5, 0x54, 0xFC, 0x8D, 0x8E, 0x54, 0xA2, 
                0x8C, 0x19, 0xEE, 0x07, 0x89, 0xE9, 0x2A, 0x8F, 0xF7, 0x0F, 0xF5, 0xEA, 0x58, 0xAB, 0x60, 0x2C, 
                0x38, 0x6E, 0xE6, 0xE0, 0x52, 0x21, 0xCE, 0xEA, 0xBE, 0x00, 0x55, 0xC8, 0xCE, 0x52, 0x7F, 0x5F, 
                0x4C, 0xC3, 0x43, 0x20, 0xDC, 0xA0, 0x21, 0x46, 0x5B, 0xF8, 0xF4, 0x9D, 0x66, 0x36, 0x75, 0xA6, 
            });

        byte[] derivedKey = ApplicationKeySupport.deriveApplicationKey(keyId, keySource, null, diversifier, expectedDerivedKey.length);
        
        assertEqual(derivedKey, expectedDerivedKey, "Derived key");
    }
    
    static class TestKeySource implements ApplicationKeySupport.ConstituentKeySource
    {
        @Override
        public byte[] getKey(int keyId) throws Exception
        {
            if (keyId == WeaveKeyId.ClientRootKey)
            {
                return toByteArray(new int[] 
                {
                    0xA2, 0x58, 0x83, 0x0C, 0xEE, 0xF6, 0x4F, 0x12, 0x21, 0x3C, 0xFA, 0xA1, 0xF0, 0xA5, 0xFC, 0x69,
                    0x26, 0x69, 0xC6, 0x47, 0x4C, 0x76, 0x38, 0xE6, 0xBE, 0xF9, 0xAD, 0x02, 0xD9, 0xD5, 0x4C, 0xAC,
                });
            }

            if (keyId == WeaveKeyId.ServiceRootKey)
            {
                return toByteArray(new int[] 
                {
                    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
                    0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF
                });
            }

            if (keyId == WeaveKeyId.makeEpochKeyId(3))
            {
                return toByteArray(new int[]
                {
                    0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
                    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F
                });
            }

            if (keyId == WeaveKeyId.makeAppGroupMasterKeyId(10))
            {
                return toByteArray(new int[]
                {
                    0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8, 0xE7, 0xE6, 0xE5, 0xE4, 0xE3, 0xE2, 0xE1, 0xE0,
                    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
                });
            }

            if (keyId == WeaveKeyId.makeAppGroupMasterKeyId(54))
            {
                return toByteArray(new int[]
                {
                    0x7F, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70,
                    0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF
                });
            }

            throw new IllegalArgumentException(String.format("Unexpected key id requested: %08X", keyId));
        }
    };
}
