/*
 * 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
Author: Andreas Sterbenz
Since: 1.6
/** * 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(); } }