/* |
|
* Copyright (c) 2006, 2014, 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 sun.security.util; |
|
import java.io.IOException; |
|
import java.security.*; |
|
import java.security.spec.*; |
|
/** |
|
* This class implements encoding and decoding of Elliptic Curve parameters |
|
* as specified in RFC 3279. |
|
* |
|
* However, only named curves are currently supported. |
|
* |
|
* ASN.1 from RFC 3279 follows. Note that X9.62 (2005) has added some additional |
|
* options. |
|
* |
|
* <pre> |
|
* EcpkParameters ::= CHOICE { |
|
* ecParameters ECParameters, |
|
* namedCurve OBJECT IDENTIFIER, |
|
* implicitlyCA NULL } |
|
* |
|
* ECParameters ::= SEQUENCE { |
|
* version ECPVer, -- version is always 1 |
|
* fieldID FieldID, -- identifies the finite field over |
|
* -- which the curve is defined |
|
* curve Curve, -- coefficients a and b of the |
|
* -- elliptic curve |
|
* base ECPoint, -- specifies the base point P |
|
* -- on the elliptic curve |
|
* order INTEGER, -- the order n of the base point |
|
* cofactor INTEGER OPTIONAL -- The integer h = #E(Fq)/n |
|
* } |
|
* |
|
* ECPVer ::= INTEGER {ecpVer1(1)} |
|
* |
|
* Curve ::= SEQUENCE { |
|
* a FieldElement, |
|
* b FieldElement, |
|
* seed BIT STRING OPTIONAL } |
|
* |
|
* FieldElement ::= OCTET STRING |
|
* |
|
* ECPoint ::= OCTET STRING |
|
* </pre> |
|
* |
|
* @since 1.6 |
|
* @author Andreas Sterbenz |
|
*/ |
|
public final class ECParameters extends AlgorithmParametersSpi { |
|
// used by ECPublicKeyImpl and ECPrivateKeyImpl |
|
public static AlgorithmParameters getAlgorithmParameters(ECParameterSpec spec) |
|
throws InvalidKeyException { |
|
try { |
|
AlgorithmParameters params = |
|
AlgorithmParameters.getInstance("EC", "SunEC"); |
|
params.init(spec); |
|
return params; |
|
} catch (GeneralSecurityException e) { |
|
throw new InvalidKeyException("EC parameters error", e); |
|
} |
|
} |
|
/* |
|
* The parameters these AlgorithmParameters object represents. |
|
* Currently, it is always an instance of NamedCurve. |
|
*/ |
|
private NamedCurve namedCurve; |
|
// A public constructor is required by AlgorithmParameters class. |
|
public ECParameters() { |
|
// empty |
|
} |
|
// AlgorithmParameterSpi methods |
|
protected void engineInit(AlgorithmParameterSpec paramSpec) |
|
throws InvalidParameterSpecException { |
|
if (paramSpec == null) { |
|
throw new InvalidParameterSpecException |
|
("paramSpec must not be null"); |
|
} |
|
if (paramSpec instanceof NamedCurve) { |
|
namedCurve = (NamedCurve)paramSpec; |
|
return; |
|
} |
|
if (paramSpec instanceof ECParameterSpec) { |
|
namedCurve = CurveDB.lookup((ECParameterSpec)paramSpec); |
|
} else if (paramSpec instanceof ECGenParameterSpec) { |
|
String name = ((ECGenParameterSpec)paramSpec).getName(); |
|
namedCurve = CurveDB.lookup(name); |
|
} else if (paramSpec instanceof ECKeySizeParameterSpec) { |
|
int keySize = ((ECKeySizeParameterSpec)paramSpec).getKeySize(); |
|
namedCurve = CurveDB.lookup(keySize); |
|
} else { |
|
throw new InvalidParameterSpecException |
|
("Only ECParameterSpec and ECGenParameterSpec supported"); |
|
} |
|
if (namedCurve == null) { |
|
throw new InvalidParameterSpecException( |
|
"Not a supported curve: " + paramSpec); |
|
} |
|
} |
|
protected void engineInit(byte[] params) throws IOException { |
|
DerValue encodedParams = new DerValue(params); |
|
if (encodedParams.tag == DerValue.tag_ObjectId) { |
|
ObjectIdentifier oid = encodedParams.getOID(); |
|
NamedCurve spec = CurveDB.lookup(oid.toString()); |
|
if (spec == null) { |
|
throw new IOException("Unknown named curve: " + oid); |
|
} |
|
namedCurve = spec; |
|
return; |
|
} |
|
throw new IOException("Only named ECParameters supported"); |
|
// The code below is incomplete. |
|
// It is left as a starting point for a complete parsing implementation. |
|
/* |
|
if (encodedParams.tag != DerValue.tag_Sequence) { |
|
throw new IOException("Unsupported EC parameters, tag: " + |
|
encodedParams.tag); |
|
} |
|
encodedParams.data.reset(); |
|
DerInputStream in = encodedParams.data; |
|
int version = in.getInteger(); |
|
if (version != 1) { |
|
throw new IOException("Unsupported EC parameters version: " + |
|
version); |
|
} |
|
ECField field = parseField(in); |
|
EllipticCurve curve = parseCurve(in, field); |
|
ECPoint point = parsePoint(in, curve); |
|
BigInteger order = in.getBigInteger(); |
|
int cofactor = 0; |
|
if (in.available() != 0) { |
|
cofactor = in.getInteger(); |
|
} |
|
// XXX HashAlgorithm optional |
|
if (encodedParams.data.available() != 0) { |
|
throw new IOException("encoded params have " + |
|
encodedParams.data.available() + |
|
" extra bytes"); |
|
} |
|
return new ECParameterSpec(curve, point, order, cofactor); |
|
*/ |
|
} |
|
protected void engineInit(byte[] params, String decodingMethod) |
|
throws IOException { |
|
engineInit(params); |
|
} |
|
protected <T extends AlgorithmParameterSpec> T |
|
engineGetParameterSpec(Class<T> spec) |
|
throws InvalidParameterSpecException { |
|
if (spec.isAssignableFrom(ECParameterSpec.class)) { |
|
return spec.cast(namedCurve); |
|
} |
|
if (spec.isAssignableFrom(ECGenParameterSpec.class)) { |
|
// Ensure the name is the Object ID |
|
String name = namedCurve.getObjectId(); |
|
return spec.cast(new ECGenParameterSpec(name)); |
|
} |
|
if (spec.isAssignableFrom(ECKeySizeParameterSpec.class)) { |
|
int keySize = namedCurve.getCurve().getField().getFieldSize(); |
|
return spec.cast(new ECKeySizeParameterSpec(keySize)); |
|
} |
|
throw new InvalidParameterSpecException( |
|
"Only ECParameterSpec and ECGenParameterSpec supported"); |
|
} |
|
protected byte[] engineGetEncoded() throws IOException { |
|
return namedCurve.getEncoded(); |
|
} |
|
protected byte[] engineGetEncoded(String encodingMethod) |
|
throws IOException { |
|
return engineGetEncoded(); |
|
} |
|
protected String engineToString() { |
|
if (namedCurve == null) { |
|
return "Not initialized"; |
|
} |
|
return namedCurve.toString(); |
|
} |
|
} |
|