1 /* 2 * Copyright (C) 2012 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.math.BigInteger; 20 import java.security.InvalidAlgorithmParameterException; 21 import java.security.InvalidParameterException; 22 import java.security.spec.ECField; 23 import java.security.spec.ECFieldF2m; 24 import java.security.spec.ECFieldFp; 25 import java.security.spec.ECParameterSpec; 26 import java.security.spec.ECPoint; 27 import java.security.spec.EllipticCurve; 28 29 public final class OpenSSLECGroupContext { 30 private final long groupCtx; 31 OpenSSLECGroupContext(long groupCtx)32 public OpenSSLECGroupContext(long groupCtx) { 33 this.groupCtx = groupCtx; 34 } 35 getCurveByName(String curveName)36 public static OpenSSLECGroupContext getCurveByName(String curveName) { 37 // Workaround for OpenSSL not supporting SECG names for NIST P-192 and P-256 38 // (aka ANSI X9.62 prime192v1 and prime256v1) curve names. 39 if ("secp256r1".equals(curveName)) { 40 curveName = "prime256v1"; 41 } else if ("secp192r1".equals(curveName)) { 42 curveName = "prime192v1"; 43 } 44 45 final long ctx = NativeCrypto.EC_GROUP_new_by_curve_name(curveName); 46 if (ctx == 0) { 47 return null; 48 } 49 50 NativeCrypto.EC_GROUP_set_point_conversion_form(ctx, 51 NativeCrypto.POINT_CONVERSION_UNCOMPRESSED); 52 NativeCrypto.EC_GROUP_set_asn1_flag(ctx, NativeCrypto.OPENSSL_EC_NAMED_CURVE); 53 54 return new OpenSSLECGroupContext(ctx); 55 } 56 getInstance(int type, BigInteger p, BigInteger a, BigInteger b, BigInteger x, BigInteger y, BigInteger n, BigInteger h)57 public static OpenSSLECGroupContext getInstance(int type, BigInteger p, BigInteger a, 58 BigInteger b, BigInteger x, BigInteger y, BigInteger n, BigInteger h) { 59 final long ctx = NativeCrypto.EC_GROUP_new_curve(type, p.toByteArray(), a.toByteArray(), 60 b.toByteArray()); 61 if (ctx == 0) { 62 return null; 63 } 64 65 NativeCrypto.EC_GROUP_set_point_conversion_form(ctx, 66 NativeCrypto.POINT_CONVERSION_UNCOMPRESSED); 67 68 OpenSSLECGroupContext group = new OpenSSLECGroupContext(ctx); 69 70 OpenSSLECPointContext generator = new OpenSSLECPointContext(group, 71 NativeCrypto.EC_POINT_new(ctx)); 72 73 NativeCrypto.EC_POINT_set_affine_coordinates(ctx, generator.getContext(), 74 x.toByteArray(), y.toByteArray()); 75 76 NativeCrypto.EC_GROUP_set_generator(ctx, generator.getContext(), n.toByteArray(), 77 h.toByteArray()); 78 79 return group; 80 } 81 82 @Override finalize()83 protected void finalize() throws Throwable { 84 try { 85 if (groupCtx != 0) { 86 NativeCrypto.EC_GROUP_clear_free(groupCtx); 87 } 88 } finally { 89 super.finalize(); 90 } 91 } 92 93 @Override equals(Object o)94 public boolean equals(Object o) { 95 if (!(o instanceof OpenSSLECGroupContext)) { 96 return false; 97 } 98 99 final OpenSSLECGroupContext other = (OpenSSLECGroupContext) o; 100 return NativeCrypto.EC_GROUP_cmp(groupCtx, other.groupCtx); 101 } 102 103 @Override hashCode()104 public int hashCode() { 105 // TODO Auto-generated method stub 106 return super.hashCode(); 107 } 108 getContext()109 public long getContext() { 110 return groupCtx; 111 } 112 getInstance(ECParameterSpec params)113 public static OpenSSLECGroupContext getInstance(ECParameterSpec params) 114 throws InvalidAlgorithmParameterException { 115 final String curveName = Platform.getCurveName(params); 116 if (curveName != null) { 117 return OpenSSLECGroupContext.getCurveByName(curveName); 118 } 119 120 final EllipticCurve curve = params.getCurve(); 121 final ECField field = curve.getField(); 122 123 final int type; 124 final BigInteger p; 125 if (field instanceof ECFieldFp) { 126 type = NativeCrypto.EC_CURVE_GFP; 127 p = ((ECFieldFp) field).getP(); 128 } else if (field instanceof ECFieldF2m) { 129 type = NativeCrypto.EC_CURVE_GF2M; 130 p = ((ECFieldF2m) field).getReductionPolynomial(); 131 } else { 132 throw new InvalidParameterException("unhandled field class " 133 + field.getClass().getName()); 134 } 135 136 final ECPoint generator = params.getGenerator(); 137 return OpenSSLECGroupContext.getInstance(type, p, curve.getA(), curve.getB(), 138 generator.getAffineX(), generator.getAffineY(), params.getOrder(), 139 BigInteger.valueOf(params.getCofactor())); 140 } 141 getECParameterSpec()142 public ECParameterSpec getECParameterSpec() { 143 final String curveName = NativeCrypto.EC_GROUP_get_curve_name(groupCtx); 144 145 final byte[][] curveParams = NativeCrypto.EC_GROUP_get_curve(groupCtx); 146 final BigInteger p = new BigInteger(curveParams[0]); 147 final BigInteger a = new BigInteger(curveParams[1]); 148 final BigInteger b = new BigInteger(curveParams[2]); 149 150 final ECField field; 151 final int type = NativeCrypto.get_EC_GROUP_type(groupCtx); 152 if (type == NativeCrypto.EC_CURVE_GFP) { 153 field = new ECFieldFp(p); 154 } else if (type == NativeCrypto.EC_CURVE_GF2M) { 155 field = new ECFieldF2m(p.bitLength() - 1, p); 156 } else { 157 throw new RuntimeException("unknown curve type " + type); 158 } 159 160 final EllipticCurve curve = new EllipticCurve(field, a, b); 161 162 final OpenSSLECPointContext generatorCtx = new OpenSSLECPointContext(this, 163 NativeCrypto.EC_GROUP_get_generator(groupCtx)); 164 final ECPoint generator = generatorCtx.getECPoint(); 165 166 final BigInteger order = new BigInteger(NativeCrypto.EC_GROUP_get_order(groupCtx)); 167 final BigInteger cofactor = new BigInteger(NativeCrypto.EC_GROUP_get_cofactor(groupCtx)); 168 169 ECParameterSpec spec = new ECParameterSpec(curve, generator, order, cofactor.intValue()); 170 Platform.setCurveName(spec, curveName); 171 return spec; 172 } 173 } 174