1package org.bouncycastle.jce.provider;
2
3import java.security.Permission;
4import java.util.Collections;
5import java.util.HashMap;
6import java.util.HashSet;
7import java.util.Map;
8import java.util.Set;
9
10import javax.crypto.spec.DHParameterSpec;
11
12import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util;
13import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
14import org.bouncycastle.jcajce.provider.config.ProviderConfiguration;
15import org.bouncycastle.jcajce.provider.config.ProviderConfigurationPermission;
16import org.bouncycastle.jce.spec.ECParameterSpec;
17
18class BouncyCastleProviderConfiguration
19    implements ProviderConfiguration
20{
21    private static Permission BC_EC_LOCAL_PERMISSION = new ProviderConfigurationPermission(
22        BouncyCastleProvider.PROVIDER_NAME, ConfigurableProvider.THREAD_LOCAL_EC_IMPLICITLY_CA);
23    private static Permission BC_EC_PERMISSION = new ProviderConfigurationPermission(
24        BouncyCastleProvider.PROVIDER_NAME, ConfigurableProvider.EC_IMPLICITLY_CA);
25    private static Permission BC_DH_LOCAL_PERMISSION = new ProviderConfigurationPermission(
26        BouncyCastleProvider.PROVIDER_NAME, ConfigurableProvider.THREAD_LOCAL_DH_DEFAULT_PARAMS);
27    private static Permission BC_DH_PERMISSION = new ProviderConfigurationPermission(
28        BouncyCastleProvider.PROVIDER_NAME, ConfigurableProvider.DH_DEFAULT_PARAMS);
29    private static Permission BC_EC_CURVE_PERMISSION = new ProviderConfigurationPermission(
30        BouncyCastleProvider.PROVIDER_NAME, ConfigurableProvider.ACCEPTABLE_EC_CURVES);
31    private static Permission BC_ADDITIONAL_EC_CURVE_PERMISSION = new ProviderConfigurationPermission(
32        BouncyCastleProvider.PROVIDER_NAME, ConfigurableProvider.ADDITIONAL_EC_PARAMETERS);
33
34    private ThreadLocal ecThreadSpec = new ThreadLocal();
35    private ThreadLocal dhThreadSpec = new ThreadLocal();
36
37    private volatile ECParameterSpec ecImplicitCaParams;
38    private volatile Object dhDefaultParams;
39    private volatile Set acceptableNamedCurves = new HashSet();
40    private volatile Map additionalECParameters = new HashMap();
41
42    void setParameter(String parameterName, Object parameter)
43    {
44        SecurityManager securityManager = System.getSecurityManager();
45
46        if (parameterName.equals(ConfigurableProvider.THREAD_LOCAL_EC_IMPLICITLY_CA))
47        {
48            ECParameterSpec curveSpec;
49
50            if (securityManager != null)
51            {
52                securityManager.checkPermission(BC_EC_LOCAL_PERMISSION);
53            }
54
55            if (parameter instanceof ECParameterSpec || parameter == null)
56            {
57                curveSpec = (ECParameterSpec)parameter;
58            }
59            else  // assume java.security.spec
60            {
61                curveSpec = EC5Util.convertSpec((java.security.spec.ECParameterSpec)parameter, false);
62            }
63
64            if (curveSpec == null)
65            {
66                ecThreadSpec.remove();
67            }
68            else
69            {
70                ecThreadSpec.set(curveSpec);
71            }
72        }
73        else if (parameterName.equals(ConfigurableProvider.EC_IMPLICITLY_CA))
74        {
75            if (securityManager != null)
76            {
77                securityManager.checkPermission(BC_EC_PERMISSION);
78            }
79
80            if (parameter instanceof ECParameterSpec || parameter == null)
81            {
82                ecImplicitCaParams = (ECParameterSpec)parameter;
83            }
84            else  // assume java.security.spec
85            {
86                ecImplicitCaParams = EC5Util.convertSpec((java.security.spec.ECParameterSpec)parameter, false);
87            }
88        }
89        else if (parameterName.equals(ConfigurableProvider.THREAD_LOCAL_DH_DEFAULT_PARAMS))
90        {
91            Object dhSpec;
92
93            if (securityManager != null)
94            {
95                securityManager.checkPermission(BC_DH_LOCAL_PERMISSION);
96            }
97
98            if (parameter instanceof DHParameterSpec || parameter instanceof DHParameterSpec[] || parameter == null)
99            {
100                dhSpec = parameter;
101            }
102            else
103            {
104                throw new IllegalArgumentException("not a valid DHParameterSpec");
105            }
106
107            if (dhSpec == null)
108            {
109                dhThreadSpec.remove();
110            }
111            else
112            {
113                dhThreadSpec.set(dhSpec);
114            }
115        }
116        else if (parameterName.equals(ConfigurableProvider.DH_DEFAULT_PARAMS))
117        {
118            if (securityManager != null)
119            {
120                securityManager.checkPermission(BC_DH_PERMISSION);
121            }
122
123            if (parameter instanceof DHParameterSpec || parameter instanceof DHParameterSpec[] || parameter == null)
124            {
125                dhDefaultParams = parameter;
126            }
127            else
128            {
129                throw new IllegalArgumentException("not a valid DHParameterSpec or DHParameterSpec[]");
130            }
131        }
132        else if (parameterName.equals(ConfigurableProvider.ACCEPTABLE_EC_CURVES))
133        {
134            if (securityManager != null)
135            {
136                securityManager.checkPermission(BC_EC_CURVE_PERMISSION);
137            }
138
139            this.acceptableNamedCurves = (Set)parameter;
140        }
141        else if (parameterName.equals(ConfigurableProvider.ADDITIONAL_EC_PARAMETERS))
142        {
143            if (securityManager != null)
144            {
145                securityManager.checkPermission(BC_ADDITIONAL_EC_CURVE_PERMISSION);
146            }
147
148            this.additionalECParameters = (Map)parameter;
149        }
150    }
151
152    public ECParameterSpec getEcImplicitlyCa()
153    {
154        ECParameterSpec spec = (ECParameterSpec)ecThreadSpec.get();
155
156        if (spec != null)
157        {
158            return spec;
159        }
160
161        return ecImplicitCaParams;
162    }
163
164    public DHParameterSpec getDHDefaultParameters(int keySize)
165    {
166        Object params = dhThreadSpec.get();
167        if (params == null)
168        {
169            params = dhDefaultParams;
170        }
171
172        if (params instanceof DHParameterSpec)
173        {
174            DHParameterSpec spec = (DHParameterSpec)params;
175
176            if (spec.getP().bitLength() == keySize)
177            {
178                return spec;
179            }
180        }
181        else if (params instanceof DHParameterSpec[])
182        {
183            DHParameterSpec[] specs = (DHParameterSpec[])params;
184
185            for (int i = 0; i != specs.length; i++)
186            {
187                if (specs[i].getP().bitLength() == keySize)
188                {
189                    return specs[i];
190                }
191            }
192        }
193
194        return null;
195    }
196
197    public Set getAcceptableNamedCurves()
198    {
199        return Collections.unmodifiableSet(acceptableNamedCurves);
200    }
201
202    public Map getAdditionalECParameters()
203    {
204        return Collections.unmodifiableMap(additionalECParameters);
205    }
206}
207