/*
 * Copyright 2005-2007 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package sun.security.mscapi;

import java.security.*;
import java.security.Key;
import java.security.interfaces.*;
import java.security.spec.*;

import javax.crypto.*;
import javax.crypto.spec.*;

/**
 * RSA cipher implementation using the Microsoft Crypto API.
 * Supports RSA en/decryption and signing/verifying using PKCS#1 v1.5 padding.
 *
 * Objects should be instantiated by calling Cipher.getInstance() using the
 * following algorithm name:
 *
 *  . "RSA/ECB/PKCS1Padding" (or "RSA") for PKCS#1 padding. The mode (blocktype)
 *    is selected based on the en/decryption mode and public/private key used.
 *
 * We only do one RSA operation per doFinal() call. If the application passes
 * more data via calls to update() or doFinal(), we throw an
 * IllegalBlockSizeException when doFinal() is called (see JCE API spec).
 * Bulk encryption using RSA does not make sense and is not standardized.
 *
 * Note: RSA keys should be at least 512 bits long
 *
 * @since   1.6
 * @author  Andreas Sterbenz
 * @author  Vincent Ryan
 */
public final class RSACipher extends CipherSpi {

    // constant for an empty byte array
    private final static byte[] B0 = new byte[0];

    // mode constant for public key encryption
    private final static int MODE_ENCRYPT = 1;
    // mode constant for private key decryption
    private final static int MODE_DECRYPT = 2;
    // mode constant for private key encryption (signing)
    private final static int MODE_SIGN    = 3;
    // mode constant for public key decryption (verifying)
    private final static int MODE_VERIFY  = 4;

    // constant for PKCS#1 v1.5 RSA
    private final static String PAD_PKCS1 = "PKCS1Padding";
    private final static int PAD_PKCS1_LENGTH = 11;

    // current mode, one of MODE_* above. Set when init() is called
    private int mode;

    // active padding type, one of PAD_* above. Set by setPadding()
    private String paddingType;
    private int paddingLength = 0;

    // buffer for the data
    private byte[] buffer;
    // offset into the buffer (number of bytes buffered)
    private int bufOfs;

    // size of the output (the length of the key).
    private int outputSize;

    // the public key, if we were initialized using a public key
    private sun.security.mscapi.Key publicKey;
    // the private key, if we were initialized using a private key
    private sun.security.mscapi.Key privateKey;

    public RSACipher() {
        SunMSCAPI.verifySelfIntegrity(getClass());
        paddingType = PAD_PKCS1;
    }

    // modes do not make sense for RSA, but allow ECB
    // see JCE spec
    protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
        if (mode.equalsIgnoreCase("ECB") == false) {
            throw new NoSuchAlgorithmException("Unsupported mode " + mode);
        }
    }

    // set the padding type
    // see JCE spec
    protected void engineSetPadding(String paddingName)
            throws NoSuchPaddingException {
        if (paddingName.equalsIgnoreCase(PAD_PKCS1)) {
            paddingType = PAD_PKCS1;
        } else {
            throw new NoSuchPaddingException
                ("Padding " + paddingName + " not supported");
        }
    }

    // return 0 as block size, we are not a block cipher
    // see JCE spec
    protected int engineGetBlockSize() {
        return 0;
    }

    // return the output size
    // see JCE spec
    protected int engineGetOutputSize(int inputLen) {
        return outputSize;
    }

    // no iv, return null
    // see JCE spec
    protected byte[] engineGetIV() {
        return null;
    }

    // no parameters, return null
    // see JCE spec
    protected AlgorithmParameters engineGetParameters() {
        return null;
    }

    // see JCE spec
    protected void engineInit(int opmode, Key key, SecureRandom random)
            throws InvalidKeyException {
        init(opmode, key);
    }

    // see JCE spec
    protected void engineInit(int opmode, Key key,
            AlgorithmParameterSpec params, SecureRandom random)
            throws InvalidKeyException, InvalidAlgorithmParameterException {

        if (params != null) {
            throw new InvalidAlgorithmParameterException
                ("Parameters not supported");
        }
        init(opmode, key);
    }

    // see JCE spec
    protected void engineInit(int opmode, Key key,
            AlgorithmParameters params, SecureRandom random)
            throws InvalidKeyException, InvalidAlgorithmParameterException {

        if (params != null) {
            throw new InvalidAlgorithmParameterException
                ("Parameters not supported");
        }
        init(opmode, key);
    }

    // initialize this cipher
    private void init(int opmode, Key key) throws InvalidKeyException {

        boolean encrypt;

        switch (opmode) {
        case Cipher.ENCRYPT_MODE:
        case Cipher.WRAP_MODE:
            paddingLength = PAD_PKCS1_LENGTH;
            encrypt = true;
            break;
        case Cipher.DECRYPT_MODE:
        case Cipher.UNWRAP_MODE:
            paddingLength = 0; // reset
            encrypt = false;
            break;
        default:
            throw new InvalidKeyException("Unknown mode: " + opmode);
        }
        if (!(key instanceof sun.security.mscapi.Key)) {
            throw new InvalidKeyException("Unsupported key type: " + key);
        }

        if (key instanceof PublicKey) {
            mode = encrypt ? MODE_ENCRYPT : MODE_VERIFY;
            publicKey = (sun.security.mscapi.Key)key;
            privateKey = null;
            outputSize = publicKey.bitLength() / 8;
        } else if (key instanceof PrivateKey) {
            mode = encrypt ? MODE_SIGN : MODE_DECRYPT;
            privateKey = (sun.security.mscapi.Key)key;
            publicKey = null;
            outputSize = privateKey.bitLength() / 8;
        } else {
            throw new InvalidKeyException("Unknown key type: " + key);
        }

        bufOfs = 0;
        buffer = new byte[outputSize];
    }

    // internal update method
    private void update(byte[] in, int inOfs, int inLen) {
        if ((inLen == 0) || (in == null)) {
            return;
        }
        if (bufOfs + inLen > (buffer.length - paddingLength)) {
            bufOfs = buffer.length + 1;
            return;
        }
        System.arraycopy(in, inOfs, buffer, bufOfs, inLen);
        bufOfs += inLen;
    }

    // internal doFinal() method. Here we perform the actual RSA operation
    private byte[] doFinal() throws BadPaddingException,
            IllegalBlockSizeException {
        if (bufOfs > buffer.length) {
            throw new IllegalBlockSizeException("Data must not be longer "
                + "than " + (buffer.length - paddingLength)  + " bytes");
        }

        try {
            byte[] data = buffer;
            switch (mode) {
            case MODE_SIGN:
                return encryptDecrypt(data, bufOfs,
                    privateKey.getHCryptKey(), true);

            case MODE_VERIFY:
                return encryptDecrypt(data, bufOfs,
                    publicKey.getHCryptKey(), false);

            case MODE_ENCRYPT:
                return encryptDecrypt(data, bufOfs,
                    publicKey.getHCryptKey(), true);

            case MODE_DECRYPT:
                return encryptDecrypt(data, bufOfs,
                    privateKey.getHCryptKey(), false);

            default:
                throw new AssertionError("Internal error");
            }

        } catch (KeyException e) {
            throw new ProviderException(e);

        } finally {
            bufOfs = 0;
        }
    }

    // see JCE spec
    protected byte[] engineUpdate(byte[] in, int inOfs, int inLen) {
        update(in, inOfs, inLen);
        return B0;
    }

    // see JCE spec
    protected int engineUpdate(byte[] in, int inOfs, int inLen, byte[] out,
            int outOfs) {
        update(in, inOfs, inLen);
        return 0;
    }

    // see JCE spec
    protected byte[] engineDoFinal(byte[] in, int inOfs, int inLen)
            throws BadPaddingException, IllegalBlockSizeException {
        update(in, inOfs, inLen);
        return doFinal();
    }

    // see JCE spec
    protected int engineDoFinal(byte[] in, int inOfs, int inLen, byte[] out,
            int outOfs) throws ShortBufferException, BadPaddingException,
            IllegalBlockSizeException {
        if (outputSize > out.length - outOfs) {
            throw new ShortBufferException
                ("Need " + outputSize + " bytes for output");
        }
        update(in, inOfs, inLen);
        byte[] result = doFinal();
        int n = result.length;
        System.arraycopy(result, 0, out, outOfs, n);
        return n;
    }

    // see JCE spec
    protected byte[] engineWrap(Key key) throws InvalidKeyException,
            IllegalBlockSizeException {
        byte[] encoded = key.getEncoded(); // TODO - unextractable key
        if ((encoded == null) || (encoded.length == 0)) {
            throw new InvalidKeyException("Could not obtain encoded key");
        }
        if (encoded.length > buffer.length) {
            throw new InvalidKeyException("Key is too long for wrapping");
        }
        update(encoded, 0, encoded.length);
        try {
            return doFinal();
        } catch (BadPaddingException e) {
            // should not occur
            throw new InvalidKeyException("Wrapping failed", e);
        }
    }

    // see JCE spec
    protected java.security.Key engineUnwrap(byte[] wrappedKey, String algorithm,
            int type) throws InvalidKeyException, NoSuchAlgorithmException {

        if (wrappedKey.length > buffer.length) {
            throw new InvalidKeyException("Key is too long for unwrapping");
        }
        update(wrappedKey, 0, wrappedKey.length);

        try {
            byte[] encoding = doFinal();

            switch (type) {
            case Cipher.PUBLIC_KEY:
                return constructPublicKey(encoding, algorithm);

            case Cipher.PRIVATE_KEY:
                return constructPrivateKey(encoding, algorithm);

            case Cipher.SECRET_KEY:
                return constructSecretKey(encoding, algorithm);

            default:
                throw new InvalidKeyException("Unknown key type " + type);
            }

        } catch (BadPaddingException e) {
            // should not occur
            throw new InvalidKeyException("Unwrapping failed", e);

        } catch (IllegalBlockSizeException e) {
            // should not occur, handled with length check above
            throw new InvalidKeyException("Unwrapping failed", e);
        }
    }

    // see JCE spec
    protected int engineGetKeySize(Key key) throws InvalidKeyException {

        if (key instanceof sun.security.mscapi.Key) {
            return ((sun.security.mscapi.Key) key).bitLength();
        } else {
            throw new InvalidKeyException("Unsupported key type: " + key);
        }
    }

    // Construct an X.509 encoded public key.
    private static PublicKey constructPublicKey(byte[] encodedKey,
        String encodedKeyAlgorithm)
            throws InvalidKeyException, NoSuchAlgorithmException {

        try {
            KeyFactory keyFactory = KeyFactory.getInstance(encodedKeyAlgorithm);
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedKey);

            return keyFactory.generatePublic(keySpec);

        } catch (NoSuchAlgorithmException nsae) {
            throw new NoSuchAlgorithmException("No installed provider " +
                "supports the " + encodedKeyAlgorithm + " algorithm", nsae);

        } catch (InvalidKeySpecException ike) {
            throw new InvalidKeyException("Cannot construct public key", ike);
        }
    }

    // Construct a PKCS #8 encoded private key.
    private static PrivateKey constructPrivateKey(byte[] encodedKey,
        String encodedKeyAlgorithm)
            throws InvalidKeyException, NoSuchAlgorithmException {

        try {
            KeyFactory keyFactory = KeyFactory.getInstance(encodedKeyAlgorithm);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);

            return keyFactory.generatePrivate(keySpec);

        } catch (NoSuchAlgorithmException nsae) {
            throw new NoSuchAlgorithmException("No installed provider " +
                "supports the " + encodedKeyAlgorithm + " algorithm", nsae);

        } catch (InvalidKeySpecException ike) {
            throw new InvalidKeyException("Cannot construct private key", ike);
        }
    }

    // Construct an encoded secret key.
    private static SecretKey constructSecretKey(byte[] encodedKey,
        String encodedKeyAlgorithm) {

        return new SecretKeySpec(encodedKey, encodedKeyAlgorithm);
    }

    /*
     * Encrypt/decrypt a data buffer using Microsoft Crypto API with HCRYPTKEY.
     * It expects and returns ciphertext data in big-endian form.
     */
    private native static byte[] encryptDecrypt(byte[] data, int dataSize,
        long hCryptKey, boolean doEncrypt) throws KeyException;

}
