/*
 * Copyright (c) 2003, 2007, Oracle and/or its affiliates. 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.crypto.provider;

import java.math.BigInteger;
import java.util.*;
import java.io.*;
import sun.security.util.*;
import sun.security.x509.*;
import java.security.AlgorithmParametersSpi;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import java.security.spec.MGF1ParameterSpec;
import javax.crypto.spec.PSource;
import javax.crypto.spec.OAEPParameterSpec;

/**
 * This class implements the OAEP parameters used with the RSA
 * algorithm in OAEP padding. Here is its ASN.1 definition:
 * RSAES-OAEP-params ::= SEQUENCE {
 *   hashAlgorithm      [0] HashAlgorithm     DEFAULT sha1,
 *   maskGenAlgorithm   [1] MaskGenAlgorithm  DEFAULT mgf1SHA1,
 *   pSourceAlgorithm   [2] PSourceAlgorithm  DEFAULT pSpecifiedEmpty
 * }
 *
 * @author Valerie Peng
 *
 */

public final class OAEPParameters extends AlgorithmParametersSpi {

    private String mdName;
    private MGF1ParameterSpec mgfSpec;
    private byte[] p;
    private static ObjectIdentifier OID_MGF1;
    private static ObjectIdentifier OID_PSpecified;

    static {
        try {
            OID_MGF1 = new ObjectIdentifier(new int[] {1,2,840,113549,1,1,8});
        } catch (IOException ioe) {
            // should not happen
            OID_MGF1 = null;
        }
        try {
            OID_PSpecified =
                new ObjectIdentifier(new int[] {1,2,840,113549,1,1,9});
        } catch (IOException ioe) {
            // should not happen
            OID_PSpecified = null;
        }
    }

    public OAEPParameters() {
    }

    protected void engineInit(AlgorithmParameterSpec paramSpec)
        throws InvalidParameterSpecException {
        if (!(paramSpec instanceof OAEPParameterSpec)) {
            throw new InvalidParameterSpecException
                ("Inappropriate parameter specification");
        }
        OAEPParameterSpec spec = (OAEPParameterSpec) paramSpec;
        mdName = spec.getDigestAlgorithm();
        String mgfName = spec.getMGFAlgorithm();
        if (!mgfName.equalsIgnoreCase("MGF1")) {
            throw new InvalidParameterSpecException("Unsupported mgf " +
                mgfName + "; MGF1 only");
        }
        AlgorithmParameterSpec mgfSpec = spec.getMGFParameters();
        if (!(mgfSpec instanceof MGF1ParameterSpec)) {
            throw new InvalidParameterSpecException("Inappropriate mgf " +
                "parameters; non-null MGF1ParameterSpec only");
        }
        this.mgfSpec = (MGF1ParameterSpec) mgfSpec;
        PSource pSrc = spec.getPSource();
        if (pSrc.getAlgorithm().equals("PSpecified")) {
            p = ((PSource.PSpecified) pSrc).getValue();
        } else {
            throw new InvalidParameterSpecException("Unsupported pSource " +
                pSrc.getAlgorithm() + "; PSpecified only");
        }
    }

    private static String convertToStandardName(String internalName) {
        if (internalName.equals("SHA")) {
            return "SHA-1";
        } else if (internalName.equals("SHA256")) {
            return "SHA-256";
        } else if (internalName.equals("SHA384")) {
            return "SHA-384";
        } else if (internalName.equals("SHA512")) {
            return "SHA-512";
        } else {
            return internalName;
        }
    }

    protected void engineInit(byte[] encoded)
        throws IOException {
        DerInputStream der = new DerInputStream(encoded);
        mdName = "SHA-1";
        mgfSpec = MGF1ParameterSpec.SHA1;
        p = new byte[0];
        DerValue[] datum = der.getSequence(3);
        for (int i=0; i<datum.length; i++) {
            DerValue data = datum[i];
            if (data.isContextSpecific((byte) 0x00)) {
                // hash algid
                mdName = convertToStandardName(AlgorithmId.parse
                    (data.data.getDerValue()).getName());
            } else if (data.isContextSpecific((byte) 0x01)) {
                // mgf algid
                AlgorithmId val = AlgorithmId.parse(data.data.getDerValue());
                if (!val.getOID().equals((Object) OID_MGF1)) {
                    throw new IOException("Only MGF1 mgf is supported");
                }
                AlgorithmId params = AlgorithmId.parse(new DerValue(val.getEncodedParams()));
                String mgfDigestName = convertToStandardName(params.getName());
                if (mgfDigestName.equals("SHA-1")) {
                    mgfSpec = MGF1ParameterSpec.SHA1;
                } else if (mgfDigestName.equals("SHA-256")) {
                    mgfSpec = MGF1ParameterSpec.SHA256;
                } else if (mgfDigestName.equals("SHA-384")) {
                    mgfSpec = MGF1ParameterSpec.SHA384;
                } else if (mgfDigestName.equals("SHA-512")) {
                    mgfSpec = MGF1ParameterSpec.SHA512;
                } else {
                    throw new IOException("Unrecognized message digest algorithm");
                }
            } else if (data.isContextSpecific((byte) 0x02)) {
                // pSource algid
                AlgorithmId val = AlgorithmId.parse(data.data.getDerValue());
                if (!val.getOID().equals((Object) OID_PSpecified)) {
                    throw new IOException("Wrong OID for pSpecified");
                }
                DerInputStream dis = new DerInputStream(val.getEncodedParams());
                p = dis.getOctetString();
                if (dis.available() != 0) {
                    throw new IOException("Extra data for pSpecified");
                }
            } else {
                throw new IOException("Invalid encoded OAEPParameters");
            }
        }
    }

    protected void engineInit(byte[] encoded, String decodingMethod)
        throws IOException {
        if ((decodingMethod != null) &&
            (!decodingMethod.equalsIgnoreCase("ASN.1"))) {
            throw new IllegalArgumentException("Only support ASN.1 format");
        }
        engineInit(encoded);
    }

    protected AlgorithmParameterSpec engineGetParameterSpec(Class paramSpec)
        throws InvalidParameterSpecException {
        if (OAEPParameterSpec.class.isAssignableFrom(paramSpec)) {
            return new OAEPParameterSpec(mdName, "MGF1", mgfSpec,
                new PSource.PSpecified(p));
        } else {
            throw new InvalidParameterSpecException
                ("Inappropriate parameter specification");
        }
    }

    protected byte[] engineGetEncoded() throws IOException {
        DerOutputStream tmp = new DerOutputStream();
        DerOutputStream tmp2, tmp3;

        // MD
        AlgorithmId mdAlgId;
        try {
            mdAlgId = AlgorithmId.get(mdName);
        } catch (NoSuchAlgorithmException nsae) {
            throw new IOException("AlgorithmId " + mdName +
                                  " impl not found");
        }
        tmp2 = new DerOutputStream();
        mdAlgId.derEncode(tmp2);
        tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0),
                      tmp2);

        // MGF
        tmp2 = new DerOutputStream();
        tmp2.putOID(OID_MGF1);
        AlgorithmId mgfDigestId;
        try {
            mgfDigestId = AlgorithmId.get(mgfSpec.getDigestAlgorithm());
        } catch (NoSuchAlgorithmException nase) {
            throw new IOException("AlgorithmId " +
                    mgfSpec.getDigestAlgorithm() + " impl not found");
        }
        mgfDigestId.encode(tmp2);
        tmp3 = new DerOutputStream();
        tmp3.write(DerValue.tag_Sequence, tmp2);
        tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)1),
                  tmp3);

        // PSource
        tmp2 = new DerOutputStream();
        tmp2.putOID(OID_PSpecified);
        tmp2.putOctetString(p);
        tmp3 = new DerOutputStream();
        tmp3.write(DerValue.tag_Sequence, tmp2);
        tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)2),
                  tmp3);

        // Put all together under a SEQUENCE tag
        DerOutputStream out = new DerOutputStream();
        out.write(DerValue.tag_Sequence, tmp);
        return out.toByteArray();
    }

    protected byte[] engineGetEncoded(String encodingMethod)
        throws IOException {
        if ((encodingMethod != null) &&
            (!encodingMethod.equalsIgnoreCase("ASN.1"))) {
            throw new IllegalArgumentException("Only support ASN.1 format");
        }
        return engineGetEncoded();
    }

    protected String engineToString() {
        StringBuffer sb = new StringBuffer();
        sb.append("MD: " + mdName + "\n");
        sb.append("MGF: MGF1" + mgfSpec.getDigestAlgorithm() + "\n");
        sb.append("PSource: PSpecified " +
            (p.length==0? "":Debug.toHexString(new BigInteger(p))) + "\n");
        return sb.toString();
    }
}
