0N/A/*
3002N/A * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage com.sun.crypto.provider;
0N/A
0N/Aimport java.math.BigInteger;
0N/Aimport java.util.*;
0N/Aimport java.io.*;
0N/Aimport sun.security.util.*;
0N/Aimport sun.security.x509.*;
0N/Aimport java.security.AlgorithmParametersSpi;
0N/Aimport java.security.NoSuchAlgorithmException;
0N/Aimport java.security.spec.AlgorithmParameterSpec;
0N/Aimport java.security.spec.InvalidParameterSpecException;
0N/Aimport java.security.spec.MGF1ParameterSpec;
0N/Aimport javax.crypto.spec.PSource;
0N/Aimport javax.crypto.spec.OAEPParameterSpec;
0N/A
0N/A/**
0N/A * This class implements the OAEP parameters used with the RSA
0N/A * algorithm in OAEP padding. Here is its ASN.1 definition:
0N/A * RSAES-OAEP-params ::= SEQUENCE {
0N/A * hashAlgorithm [0] HashAlgorithm DEFAULT sha1,
0N/A * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1,
0N/A * pSourceAlgorithm [2] PSourceAlgorithm DEFAULT pSpecifiedEmpty
0N/A * }
0N/A *
0N/A * @author Valerie Peng
0N/A *
0N/A */
0N/A
0N/Apublic final class OAEPParameters extends AlgorithmParametersSpi {
0N/A
0N/A private String mdName;
0N/A private MGF1ParameterSpec mgfSpec;
0N/A private byte[] p;
0N/A private static ObjectIdentifier OID_MGF1;
0N/A private static ObjectIdentifier OID_PSpecified;
0N/A
0N/A static {
0N/A try {
0N/A OID_MGF1 = new ObjectIdentifier(new int[] {1,2,840,113549,1,1,8});
0N/A } catch (IOException ioe) {
0N/A // should not happen
0N/A OID_MGF1 = null;
0N/A }
0N/A try {
0N/A OID_PSpecified =
0N/A new ObjectIdentifier(new int[] {1,2,840,113549,1,1,9});
0N/A } catch (IOException ioe) {
0N/A // should not happen
0N/A OID_PSpecified = null;
0N/A }
0N/A }
0N/A
0N/A public OAEPParameters() {
0N/A }
0N/A
0N/A protected void engineInit(AlgorithmParameterSpec paramSpec)
0N/A throws InvalidParameterSpecException {
0N/A if (!(paramSpec instanceof OAEPParameterSpec)) {
0N/A throw new InvalidParameterSpecException
0N/A ("Inappropriate parameter specification");
0N/A }
0N/A OAEPParameterSpec spec = (OAEPParameterSpec) paramSpec;
0N/A mdName = spec.getDigestAlgorithm();
0N/A String mgfName = spec.getMGFAlgorithm();
0N/A if (!mgfName.equalsIgnoreCase("MGF1")) {
0N/A throw new InvalidParameterSpecException("Unsupported mgf " +
0N/A mgfName + "; MGF1 only");
0N/A }
0N/A AlgorithmParameterSpec mgfSpec = spec.getMGFParameters();
0N/A if (!(mgfSpec instanceof MGF1ParameterSpec)) {
0N/A throw new InvalidParameterSpecException("Inappropriate mgf " +
0N/A "parameters; non-null MGF1ParameterSpec only");
0N/A }
0N/A this.mgfSpec = (MGF1ParameterSpec) mgfSpec;
0N/A PSource pSrc = spec.getPSource();
0N/A if (pSrc.getAlgorithm().equals("PSpecified")) {
0N/A p = ((PSource.PSpecified) pSrc).getValue();
0N/A } else {
0N/A throw new InvalidParameterSpecException("Unsupported pSource " +
0N/A pSrc.getAlgorithm() + "; PSpecified only");
0N/A }
0N/A }
0N/A
0N/A private static String convertToStandardName(String internalName) {
0N/A if (internalName.equals("SHA")) {
0N/A return "SHA-1";
0N/A } else if (internalName.equals("SHA256")) {
0N/A return "SHA-256";
0N/A } else if (internalName.equals("SHA384")) {
0N/A return "SHA-384";
0N/A } else if (internalName.equals("SHA512")) {
0N/A return "SHA-512";
0N/A } else {
0N/A return internalName;
0N/A }
0N/A }
0N/A
0N/A protected void engineInit(byte[] encoded)
0N/A throws IOException {
0N/A DerInputStream der = new DerInputStream(encoded);
0N/A mdName = "SHA-1";
0N/A mgfSpec = MGF1ParameterSpec.SHA1;
0N/A p = new byte[0];
0N/A DerValue[] datum = der.getSequence(3);
0N/A for (int i=0; i<datum.length; i++) {
0N/A DerValue data = datum[i];
0N/A if (data.isContextSpecific((byte) 0x00)) {
0N/A // hash algid
0N/A mdName = convertToStandardName(AlgorithmId.parse
0N/A (data.data.getDerValue()).getName());
0N/A } else if (data.isContextSpecific((byte) 0x01)) {
0N/A // mgf algid
0N/A AlgorithmId val = AlgorithmId.parse(data.data.getDerValue());
0N/A if (!val.getOID().equals((Object) OID_MGF1)) {
0N/A throw new IOException("Only MGF1 mgf is supported");
0N/A }
3002N/A AlgorithmId params = AlgorithmId.parse(
3002N/A new DerValue(val.getEncodedParams()));
0N/A String mgfDigestName = convertToStandardName(params.getName());
0N/A if (mgfDigestName.equals("SHA-1")) {
0N/A mgfSpec = MGF1ParameterSpec.SHA1;
0N/A } else if (mgfDigestName.equals("SHA-256")) {
0N/A mgfSpec = MGF1ParameterSpec.SHA256;
0N/A } else if (mgfDigestName.equals("SHA-384")) {
0N/A mgfSpec = MGF1ParameterSpec.SHA384;
0N/A } else if (mgfDigestName.equals("SHA-512")) {
0N/A mgfSpec = MGF1ParameterSpec.SHA512;
0N/A } else {
3002N/A throw new IOException(
3002N/A "Unrecognized message digest algorithm");
0N/A }
0N/A } else if (data.isContextSpecific((byte) 0x02)) {
0N/A // pSource algid
0N/A AlgorithmId val = AlgorithmId.parse(data.data.getDerValue());
0N/A if (!val.getOID().equals((Object) OID_PSpecified)) {
0N/A throw new IOException("Wrong OID for pSpecified");
0N/A }
0N/A DerInputStream dis = new DerInputStream(val.getEncodedParams());
0N/A p = dis.getOctetString();
0N/A if (dis.available() != 0) {
0N/A throw new IOException("Extra data for pSpecified");
0N/A }
0N/A } else {
0N/A throw new IOException("Invalid encoded OAEPParameters");
0N/A }
0N/A }
0N/A }
0N/A
0N/A protected void engineInit(byte[] encoded, String decodingMethod)
0N/A throws IOException {
0N/A if ((decodingMethod != null) &&
0N/A (!decodingMethod.equalsIgnoreCase("ASN.1"))) {
0N/A throw new IllegalArgumentException("Only support ASN.1 format");
0N/A }
0N/A engineInit(encoded);
0N/A }
0N/A
0N/A protected AlgorithmParameterSpec engineGetParameterSpec(Class paramSpec)
0N/A throws InvalidParameterSpecException {
0N/A if (OAEPParameterSpec.class.isAssignableFrom(paramSpec)) {
0N/A return new OAEPParameterSpec(mdName, "MGF1", mgfSpec,
0N/A new PSource.PSpecified(p));
0N/A } else {
0N/A throw new InvalidParameterSpecException
0N/A ("Inappropriate parameter specification");
0N/A }
0N/A }
0N/A
0N/A protected byte[] engineGetEncoded() throws IOException {
0N/A DerOutputStream tmp = new DerOutputStream();
0N/A DerOutputStream tmp2, tmp3;
0N/A
0N/A // MD
0N/A AlgorithmId mdAlgId;
0N/A try {
0N/A mdAlgId = AlgorithmId.get(mdName);
0N/A } catch (NoSuchAlgorithmException nsae) {
0N/A throw new IOException("AlgorithmId " + mdName +
0N/A " impl not found");
0N/A }
0N/A tmp2 = new DerOutputStream();
0N/A mdAlgId.derEncode(tmp2);
0N/A tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0),
0N/A tmp2);
0N/A
0N/A // MGF
0N/A tmp2 = new DerOutputStream();
0N/A tmp2.putOID(OID_MGF1);
0N/A AlgorithmId mgfDigestId;
0N/A try {
0N/A mgfDigestId = AlgorithmId.get(mgfSpec.getDigestAlgorithm());
0N/A } catch (NoSuchAlgorithmException nase) {
0N/A throw new IOException("AlgorithmId " +
0N/A mgfSpec.getDigestAlgorithm() + " impl not found");
0N/A }
0N/A mgfDigestId.encode(tmp2);
0N/A tmp3 = new DerOutputStream();
0N/A tmp3.write(DerValue.tag_Sequence, tmp2);
0N/A tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)1),
0N/A tmp3);
0N/A
0N/A // PSource
0N/A tmp2 = new DerOutputStream();
0N/A tmp2.putOID(OID_PSpecified);
0N/A tmp2.putOctetString(p);
0N/A tmp3 = new DerOutputStream();
0N/A tmp3.write(DerValue.tag_Sequence, tmp2);
0N/A tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)2),
0N/A tmp3);
0N/A
0N/A // Put all together under a SEQUENCE tag
0N/A DerOutputStream out = new DerOutputStream();
0N/A out.write(DerValue.tag_Sequence, tmp);
0N/A return out.toByteArray();
0N/A }
0N/A
0N/A protected byte[] engineGetEncoded(String encodingMethod)
0N/A throws IOException {
0N/A if ((encodingMethod != null) &&
0N/A (!encodingMethod.equalsIgnoreCase("ASN.1"))) {
0N/A throw new IllegalArgumentException("Only support ASN.1 format");
0N/A }
0N/A return engineGetEncoded();
0N/A }
0N/A
0N/A protected String engineToString() {
0N/A StringBuffer sb = new StringBuffer();
0N/A sb.append("MD: " + mdName + "\n");
0N/A sb.append("MGF: MGF1" + mgfSpec.getDigestAlgorithm() + "\n");
0N/A sb.append("PSource: PSpecified " +
0N/A (p.length==0? "":Debug.toHexString(new BigInteger(p))) + "\n");
0N/A return sb.toString();
0N/A }
0N/A}