/* * 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. * *
 *    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
 * 
* * @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 engineGetParameterSpec(Class 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(); } }