/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * 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.
 */

package org.conscrypt;

import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.KeyAgreementSpi;
import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.SecretKeySpec;

/**
 * Elliptic Curve Diffie-Hellman key agreement backed by the OpenSSL engine.
 */
public final class OpenSSLECDHKeyAgreement extends KeyAgreementSpi {

    /** OpenSSL handle of the private key. Only available after the engine has been initialized. */
    private OpenSSLKey mOpenSslPrivateKey;

    /**
     * Expected length (in bytes) of the agreed key ({@link #mResult}). Only available after the
     * engine has been initialized.
     */
    private int mExpectedResultLength;

    /** Agreed key. Only available after {@link #engineDoPhase(Key, boolean)} completes. */
    private byte[] mResult;

    @Override
    public Key engineDoPhase(Key key, boolean lastPhase) throws InvalidKeyException {
        if (mOpenSslPrivateKey == null) {
            throw new IllegalStateException("Not initialized");
        }
        if (!lastPhase) {
            throw new IllegalStateException("ECDH only has one phase");
        }

        if (key == null) {
            throw new InvalidKeyException("key == null");
        }
        if (!(key instanceof PublicKey)) {
            throw new InvalidKeyException("Not a public key: " + key.getClass());
        }
        OpenSSLKey openSslPublicKey = OpenSSLKey.fromPublicKey((PublicKey) key);

        byte[] buffer = new byte[mExpectedResultLength];
        int actualResultLength = NativeCrypto.ECDH_compute_key(
                buffer,
                0,
                openSslPublicKey.getNativeRef(),
                mOpenSslPrivateKey.getNativeRef());
        byte[] result;
        if (actualResultLength == -1) {
            throw new RuntimeException("Engine returned " + actualResultLength);
        } else if (actualResultLength == mExpectedResultLength) {
            // The output is as long as expected -- use the whole buffer
            result = buffer;
        } else if (actualResultLength < mExpectedResultLength) {
            // The output is shorter than expected -- use only what's produced by the engine
            result = new byte[actualResultLength];
            System.arraycopy(buffer, 0, mResult, 0, mResult.length);
        } else {
            // The output is longer than expected
            throw new RuntimeException("Engine produced a longer than expected result. Expected: "
                + mExpectedResultLength + ", actual: " + actualResultLength);
        }
        mResult = result;

        return null; // No intermediate key
    }

    @Override
    protected int engineGenerateSecret(byte[] sharedSecret, int offset)
            throws ShortBufferException {
        checkCompleted();
        int available = sharedSecret.length - offset;
        if (mResult.length > available) {
            throw new ShortBufferException(
                    "Needed: " + mResult.length + ", available: " + available);
        }

        System.arraycopy(mResult, 0, sharedSecret, offset, mResult.length);
        return mResult.length;
    }

    @Override
    protected byte[] engineGenerateSecret() {
        checkCompleted();
        return mResult;
    }

    @Override
    protected SecretKey engineGenerateSecret(String algorithm) {
        checkCompleted();
        return new SecretKeySpec(engineGenerateSecret(), algorithm);
    }

    @Override
    protected void engineInit(Key key, SecureRandom random) throws InvalidKeyException {
        if (key == null) {
            throw new InvalidKeyException("key == null");
        }
        if (!(key instanceof PrivateKey)) {
            throw new InvalidKeyException("Not a private key: " + key.getClass());
        }

        OpenSSLKey openSslKey = OpenSSLKey.fromPrivateKey((PrivateKey) key);
        int fieldSizeBits = NativeCrypto.EC_GROUP_get_degree(new NativeRef.EC_GROUP(
                NativeCrypto.EC_KEY_get1_group(openSslKey.getNativeRef())));
        mExpectedResultLength = (fieldSizeBits + 7) / 8;
        mOpenSslPrivateKey = openSslKey;
    }

    @Override
    protected void engineInit(Key key, AlgorithmParameterSpec params,
            SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
        // ECDH doesn't need an AlgorithmParameterSpec
        if (params != null) {
          throw new InvalidAlgorithmParameterException("No algorithm parameters supported");
        }
        engineInit(key, random);
    }

    private void checkCompleted() {
        if (mResult == null) {
            throw new IllegalStateException("Key agreement not completed");
        }
    }
}
