/* | 
|
 * 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();  | 
|
}  | 
|
}  | 
|