1package org.bouncycastle.jcajce.provider.asymmetric.ec;
2
3import java.security.InvalidKeyException;
4import java.security.PrivateKey;
5import java.security.PublicKey;
6
7import org.bouncycastle.asn1.ASN1ObjectIdentifier;
8// BEGIN android-removed
9// import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves;
10// END android-removed
11import org.bouncycastle.asn1.nist.NISTNamedCurves;
12import org.bouncycastle.asn1.sec.SECNamedCurves;
13// BEGIN android-removed
14// import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves;
15// END android-removed
16import org.bouncycastle.asn1.x9.X962NamedCurves;
17import org.bouncycastle.asn1.x9.X9ECParameters;
18import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
19import org.bouncycastle.crypto.params.ECDomainParameters;
20import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
21import org.bouncycastle.crypto.params.ECPublicKeyParameters;
22import org.bouncycastle.jce.interfaces.ECPrivateKey;
23import org.bouncycastle.jce.interfaces.ECPublicKey;
24import org.bouncycastle.jce.provider.BouncyCastleProvider;
25import org.bouncycastle.jce.spec.ECParameterSpec;
26
27/**
28 * utility class for converting jce/jca ECDSA, ECDH, and ECDHC
29 * objects into their org.bouncycastle.crypto counterparts.
30 */
31public class ECUtil
32{
33    /**
34     * Returns a sorted array of middle terms of the reduction polynomial.
35     * @param k The unsorted array of middle terms of the reduction polynomial
36     * of length 1 or 3.
37     * @return the sorted array of middle terms of the reduction polynomial.
38     * This array always has length 3.
39     */
40    static int[] convertMidTerms(
41        int[] k)
42    {
43        int[] res = new int[3];
44
45        if (k.length == 1)
46        {
47            res[0] = k[0];
48        }
49        else
50        {
51            if (k.length != 3)
52            {
53                throw new IllegalArgumentException("Only Trinomials and pentanomials supported");
54            }
55
56            if (k[0] < k[1] && k[0] < k[2])
57            {
58                res[0] = k[0];
59                if (k[1] < k[2])
60                {
61                    res[1] = k[1];
62                    res[2] = k[2];
63                }
64                else
65                {
66                    res[1] = k[2];
67                    res[2] = k[1];
68                }
69            }
70            else if (k[1] < k[2])
71            {
72                res[0] = k[1];
73                if (k[0] < k[2])
74                {
75                    res[1] = k[0];
76                    res[2] = k[2];
77                }
78                else
79                {
80                    res[1] = k[2];
81                    res[2] = k[0];
82                }
83            }
84            else
85            {
86                res[0] = k[2];
87                if (k[0] < k[1])
88                {
89                    res[1] = k[0];
90                    res[2] = k[1];
91                }
92                else
93                {
94                    res[1] = k[1];
95                    res[2] = k[0];
96                }
97            }
98        }
99
100        return res;
101    }
102
103    public static AsymmetricKeyParameter generatePublicKeyParameter(
104        PublicKey    key)
105        throws InvalidKeyException
106    {
107        if (key instanceof ECPublicKey)
108        {
109            ECPublicKey    k = (ECPublicKey)key;
110            ECParameterSpec s = k.getParameters();
111
112            if (s == null)
113            {
114                s = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa();
115
116                return new ECPublicKeyParameters(
117                            ((BCECPublicKey)k).engineGetQ(),
118                            new ECDomainParameters(s.getCurve(), s.getG(), s.getN(), s.getH(), s.getSeed()));
119            }
120            else
121            {
122                return new ECPublicKeyParameters(
123                            k.getQ(),
124                            new ECDomainParameters(s.getCurve(), s.getG(), s.getN(), s.getH(), s.getSeed()));
125            }
126        }
127        else if (key instanceof java.security.interfaces.ECPublicKey)
128        {
129            java.security.interfaces.ECPublicKey pubKey = (java.security.interfaces.ECPublicKey)key;
130            ECParameterSpec s = EC5Util.convertSpec(pubKey.getParams(), false);
131            return new ECPublicKeyParameters(
132                EC5Util.convertPoint(pubKey.getParams(), pubKey.getW(), false),
133                            new ECDomainParameters(s.getCurve(), s.getG(), s.getN(), s.getH(), s.getSeed()));
134        }
135
136        throw new InvalidKeyException("cannot identify EC public key.");
137    }
138
139    public static AsymmetricKeyParameter generatePrivateKeyParameter(
140        PrivateKey    key)
141        throws InvalidKeyException
142    {
143        if (key instanceof ECPrivateKey)
144        {
145            ECPrivateKey  k = (ECPrivateKey)key;
146            ECParameterSpec s = k.getParameters();
147
148            if (s == null)
149            {
150                s = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa();
151            }
152
153            return new ECPrivateKeyParameters(
154                            k.getD(),
155                            new ECDomainParameters(s.getCurve(), s.getG(), s.getN(), s.getH(), s.getSeed()));
156        }
157
158        throw new InvalidKeyException("can't identify EC private key.");
159    }
160
161    public static ASN1ObjectIdentifier getNamedCurveOid(
162        String name)
163    {
164        ASN1ObjectIdentifier oid = X962NamedCurves.getOID(name);
165
166        if (oid == null)
167        {
168            oid = SECNamedCurves.getOID(name);
169            if (oid == null)
170            {
171                oid = NISTNamedCurves.getOID(name);
172            }
173            // BEGIN android-removed
174            // if (oid == null)
175            // {
176            //     oid = TeleTrusTNamedCurves.getOID(name);
177            // }
178            // if (oid == null)
179            // {
180            //     oid = ECGOST3410NamedCurves.getOID(name);
181            // }
182            // END android-removed
183        }
184
185        return oid;
186    }
187
188    public static X9ECParameters getNamedCurveByOid(
189        ASN1ObjectIdentifier oid)
190    {
191        X9ECParameters params = X962NamedCurves.getByOID(oid);
192
193        if (params == null)
194        {
195            params = SECNamedCurves.getByOID(oid);
196            if (params == null)
197            {
198                params = NISTNamedCurves.getByOID(oid);
199            }
200            // BEGIN android-removed
201            // if (params == null)
202            // {
203            //     params = TeleTrusTNamedCurves.getByOID(oid);
204            // }
205            // END android-removed
206        }
207
208        return params;
209    }
210
211    public static String getCurveName(
212        ASN1ObjectIdentifier oid)
213    {
214        String name = X962NamedCurves.getName(oid);
215
216        if (name == null)
217        {
218            name = SECNamedCurves.getName(oid);
219            if (name == null)
220            {
221                name = NISTNamedCurves.getName(oid);
222            }
223            // BEGIN android-removed
224            // if (name == null)
225            // {
226            //     name = TeleTrusTNamedCurves.getName(oid);
227            // }
228            // if (name == null)
229            // {
230            //     name = ECGOST3410NamedCurves.getName(oid);
231            // }
232            // END android-removed
233        }
234
235        return name;
236    }
237}
238