| /* | |
| * Copyright (c) 2006, 2024, 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, ECGenParameterSpec " + | |
| "and ECKeySizeParameterSpec 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)) { | |
| String name = namedCurve.getNameAndAliases()[0]; | |
| 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, ECGenParameterSpec " + | |
| "and ECKeySizeParameterSpec 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(); | |
| } | |
| } |