1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package org.conscrypt; 18 19 import java.io.IOException; 20 import java.security.AlgorithmParametersSpi; 21 import java.security.InvalidAlgorithmParameterException; 22 import java.security.spec.AlgorithmParameterSpec; 23 import java.security.spec.ECGenParameterSpec; 24 import java.security.spec.ECParameterSpec; 25 import java.security.spec.InvalidParameterSpecException; 26 27 /** 28 * AlgorithmParameters implementation for elliptic curves. The only supported encoding format is 29 * ASN.1, as specified in RFC 3279, section 2.3.5. However, only named curves are supported. 30 * 31 * @hide 32 */ 33 @Internal 34 public class ECParameters extends AlgorithmParametersSpi { 35 36 private OpenSSLECGroupContext curve; 37 38 @Override 39 protected void engineInit(AlgorithmParameterSpec algorithmParameterSpec) 40 throws InvalidParameterSpecException { 41 if (algorithmParameterSpec instanceof ECGenParameterSpec) { 42 String newCurveName = ((ECGenParameterSpec) algorithmParameterSpec).getName(); 43 OpenSSLECGroupContext newCurve = OpenSSLECGroupContext.getCurveByName(newCurveName); 44 if (newCurve == null) { 45 throw new InvalidParameterSpecException("Unknown EC curve name: " + newCurveName); 46 } 47 this.curve = newCurve; 48 } else if (algorithmParameterSpec instanceof ECParameterSpec) { 49 ECParameterSpec ecParamSpec = (ECParameterSpec) algorithmParameterSpec; 50 try { 51 OpenSSLECGroupContext newCurve = OpenSSLECGroupContext.getInstance(ecParamSpec); 52 if (newCurve == null) { 53 throw new InvalidParameterSpecException("Unknown EC curve: " + ecParamSpec); 54 } 55 this.curve = newCurve; 56 } catch (InvalidAlgorithmParameterException e) { 57 throw new InvalidParameterSpecException(e.getMessage()); 58 } 59 } else { 60 throw new InvalidParameterSpecException( 61 "Only ECParameterSpec and ECGenParameterSpec are supported"); 62 } 63 } 64 65 @Override 66 protected void engineInit(byte[] bytes) throws IOException { 67 long ref = NativeCrypto.EC_KEY_parse_curve_name(bytes); 68 if (ref == 0) { 69 throw new IOException("Error reading ASN.1 encoding"); 70 } 71 this.curve = new OpenSSLECGroupContext(new NativeRef.EC_GROUP(ref)); 72 } 73 74 @Override 75 protected void engineInit(byte[] bytes, String format) throws IOException { 76 if (format == null || format.equals("ASN.1")) { 77 engineInit(bytes); 78 } else { 79 throw new IOException("Unsupported format: " + format); 80 } 81 } 82 83 @Override 84 @SuppressWarnings("unchecked") 85 protected <T extends AlgorithmParameterSpec> T engineGetParameterSpec(Class<T> aClass) 86 throws InvalidParameterSpecException { 87 if (aClass == ECParameterSpec.class) { 88 return (T) curve.getECParameterSpec(); 89 } else if (aClass == ECGenParameterSpec.class) { 90 return (T) new ECGenParameterSpec(Platform.getCurveName(curve.getECParameterSpec())); 91 } else { 92 throw new InvalidParameterSpecException("Unsupported class: " + aClass); 93 } 94 } 95 96 @Override 97 protected byte[] engineGetEncoded() throws IOException { 98 return NativeCrypto.EC_KEY_marshal_curve_name(curve.getNativeRef()); 99 } 100 101 @Override 102 protected byte[] engineGetEncoded(String format) throws IOException { 103 if (format == null || format.equals("ASN.1")) { 104 return engineGetEncoded(); 105 } 106 throw new IOException("Unsupported format: " + format); 107 } 108 109 @Override 110 protected String engineToString() { 111 return "Conscrypt EC AlgorithmParameters"; 112 } 113 } 114