1 /* 2 * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.security.util; 27 28 import java.io.IOException; 29 30 import java.security.*; 31 import java.security.spec.*; 32 33 /** 34 * This class implements encoding and decoding of Elliptic Curve parameters 35 * as specified in RFC 3279. 36 * 37 * However, only named curves are currently supported. 38 * 39 * ASN.1 from RFC 3279 follows. Note that X9.62 (2005) has added some additional 40 * options. 41 * 42 * <pre> 43 * EcpkParameters ::= CHOICE { 44 * ecParameters ECParameters, 45 * namedCurve OBJECT IDENTIFIER, 46 * implicitlyCA NULL } 47 * 48 * ECParameters ::= SEQUENCE { 49 * version ECPVer, -- version is always 1 50 * fieldID FieldID, -- identifies the finite field over 51 * -- which the curve is defined 52 * curve Curve, -- coefficients a and b of the 53 * -- elliptic curve 54 * base ECPoint, -- specifies the base point P 55 * -- on the elliptic curve 56 * order INTEGER, -- the order n of the base point 57 * cofactor INTEGER OPTIONAL -- The integer h = #E(Fq)/n 58 * } 59 * 60 * ECPVer ::= INTEGER {ecpVer1(1)} 61 * 62 * Curve ::= SEQUENCE { 63 * a FieldElement, 64 * b FieldElement, 65 * seed BIT STRING OPTIONAL } 66 * 67 * FieldElement ::= OCTET STRING 68 * 69 * ECPoint ::= OCTET STRING 70 * </pre> 71 * 72 * @since 1.6 73 * @author Andreas Sterbenz 74 */ 75 public final class ECParameters extends AlgorithmParametersSpi { 76 77 // used by ECPublicKeyImpl and ECPrivateKeyImpl getAlgorithmParameters(ECParameterSpec spec)78 public static AlgorithmParameters getAlgorithmParameters(ECParameterSpec spec) 79 throws InvalidKeyException { 80 try { 81 AlgorithmParameters params = 82 AlgorithmParameters.getInstance("EC", "SunEC"); 83 params.init(spec); 84 return params; 85 } catch (GeneralSecurityException e) { 86 throw new InvalidKeyException("EC parameters error", e); 87 } 88 } 89 90 /* 91 * The parameters these AlgorithmParameters object represents. 92 * Currently, it is always an instance of NamedCurve. 93 */ 94 private NamedCurve namedCurve; 95 96 // A public constructor is required by AlgorithmParameters class. ECParameters()97 public ECParameters() { 98 // empty 99 } 100 101 // AlgorithmParameterSpi methods 102 engineInit(AlgorithmParameterSpec paramSpec)103 protected void engineInit(AlgorithmParameterSpec paramSpec) 104 throws InvalidParameterSpecException { 105 106 if (paramSpec == null) { 107 throw new InvalidParameterSpecException 108 ("paramSpec must not be null"); 109 } 110 111 if (paramSpec instanceof NamedCurve) { 112 namedCurve = (NamedCurve)paramSpec; 113 return; 114 } 115 116 if (paramSpec instanceof ECParameterSpec) { 117 namedCurve = CurveDB.lookup((ECParameterSpec)paramSpec); 118 } else if (paramSpec instanceof ECGenParameterSpec) { 119 String name = ((ECGenParameterSpec)paramSpec).getName(); 120 namedCurve = CurveDB.lookup(name); 121 } else if (paramSpec instanceof ECKeySizeParameterSpec) { 122 int keySize = ((ECKeySizeParameterSpec)paramSpec).getKeySize(); 123 namedCurve = CurveDB.lookup(keySize); 124 } else { 125 throw new InvalidParameterSpecException 126 ("Only ECParameterSpec and ECGenParameterSpec supported"); 127 } 128 129 if (namedCurve == null) { 130 throw new InvalidParameterSpecException( 131 "Not a supported curve: " + paramSpec); 132 } 133 } 134 engineInit(byte[] params)135 protected void engineInit(byte[] params) throws IOException { 136 DerValue encodedParams = new DerValue(params); 137 if (encodedParams.tag == DerValue.tag_ObjectId) { 138 ObjectIdentifier oid = encodedParams.getOID(); 139 NamedCurve spec = CurveDB.lookup(oid.toString()); 140 if (spec == null) { 141 throw new IOException("Unknown named curve: " + oid); 142 } 143 144 namedCurve = spec; 145 return; 146 } 147 148 throw new IOException("Only named ECParameters supported"); 149 150 // The code below is incomplete. 151 // It is left as a starting point for a complete parsing implementation. 152 153 /* 154 if (encodedParams.tag != DerValue.tag_Sequence) { 155 throw new IOException("Unsupported EC parameters, tag: " + 156 encodedParams.tag); 157 } 158 159 encodedParams.data.reset(); 160 161 DerInputStream in = encodedParams.data; 162 163 int version = in.getInteger(); 164 if (version != 1) { 165 throw new IOException("Unsupported EC parameters version: " + 166 version); 167 } 168 ECField field = parseField(in); 169 EllipticCurve curve = parseCurve(in, field); 170 ECPoint point = parsePoint(in, curve); 171 172 BigInteger order = in.getBigInteger(); 173 int cofactor = 0; 174 175 if (in.available() != 0) { 176 cofactor = in.getInteger(); 177 } 178 179 // XXX HashAlgorithm optional 180 181 if (encodedParams.data.available() != 0) { 182 throw new IOException("encoded params have " + 183 encodedParams.data.available() + 184 " extra bytes"); 185 } 186 187 return new ECParameterSpec(curve, point, order, cofactor); 188 */ 189 } 190 engineInit(byte[] params, String decodingMethod)191 protected void engineInit(byte[] params, String decodingMethod) 192 throws IOException { 193 engineInit(params); 194 } 195 196 protected <T extends AlgorithmParameterSpec> T engineGetParameterSpec(Class<T> spec)197 engineGetParameterSpec(Class<T> spec) 198 throws InvalidParameterSpecException { 199 200 if (spec.isAssignableFrom(ECParameterSpec.class)) { 201 return spec.cast(namedCurve); 202 } 203 204 if (spec.isAssignableFrom(ECGenParameterSpec.class)) { 205 // Ensure the name is the Object ID 206 String name = namedCurve.getObjectId(); 207 return spec.cast(new ECGenParameterSpec(name)); 208 } 209 210 if (spec.isAssignableFrom(ECKeySizeParameterSpec.class)) { 211 int keySize = namedCurve.getCurve().getField().getFieldSize(); 212 return spec.cast(new ECKeySizeParameterSpec(keySize)); 213 } 214 215 throw new InvalidParameterSpecException( 216 "Only ECParameterSpec and ECGenParameterSpec supported"); 217 } 218 engineGetEncoded()219 protected byte[] engineGetEncoded() throws IOException { 220 return namedCurve.getEncoded(); 221 } 222 engineGetEncoded(String encodingMethod)223 protected byte[] engineGetEncoded(String encodingMethod) 224 throws IOException { 225 return engineGetEncoded(); 226 } 227 engineToString()228 protected String engineToString() { 229 if (namedCurve == null) { 230 return "Not initialized"; 231 } 232 233 return namedCurve.toString(); 234 } 235 } 236 237