001 // Copyright (C) 2002 IAIK
002 // https://jce.iaik.tugraz.at
003 //
004 // Copyright (C) 2003 - 2025 Stiftung Secure Information and
005 // Communication Technologies SIC
006 // https://sic.tech
007 //
008 // All rights reserved.
009 //
010 // Redistribution and use in source and binary forms, with or without
011 // modification, are permitted provided that the following conditions
012 // are met:
013 // 1. Redistributions of source code must retain the above copyright
014 // notice, this list of conditions and the following disclaimer.
015 // 2. Redistributions in binary form must reproduce the above copyright
016 // notice, this list of conditions and the following disclaimer in the
017 // documentation and/or other materials provided with the distribution.
018 //
019 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
020 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
021 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
022 // ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
023 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
024 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
025 // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
026 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
027 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
028 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
029 // SUCH DAMAGE.
030
031 // Copyright (C) 2002 IAIK
032 // https://sic.tech
033 //
034 // Copyright (C) 2003 - 2025 Stiftung Secure Information and
035 // Communication Technologies SIC
036 // https://sic.tech
037 //
038 // All rights reserved.
039 //
040 // This source is provided for inspection purposes and recompilation only,
041 // unless specified differently in a contract with IAIK. This source has to
042 // be kept in strict confidence and must not be disclosed to any third party
043 // under any circumstances. Redistribution in source and binary forms, with
044 // or without modification, are <not> permitted in any case!
045 //
046 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
047 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
048 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
049 // ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
050 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
051 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
052 // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
053 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
054 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
055 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
056 // SUCH DAMAGE.
057 //
058 // $Header: /IAIK-CMS/current/src/demo/cms/ecc/ECCDemoUtil.java 18 12.02.25 17:58 Dbratko $
059 // $Revision: 18 $
060
061 package demo.cms.ecc;
062
063
064
065 import java.lang.reflect.Constructor;
066 import java.lang.reflect.Field;
067 import java.lang.reflect.Method;
068 import java.security.InvalidAlgorithmParameterException;
069 import java.security.InvalidKeyException;
070 import java.security.NoSuchAlgorithmException;
071 import java.security.NoSuchProviderException;
072 import java.security.PrivateKey;
073 import java.security.Provider;
074 import java.security.Security;
075 import java.security.cert.CertificateException;
076 import java.security.spec.AlgorithmParameterSpec;
077 import java.security.spec.InvalidParameterSpecException;
078
079 import iaik.asn1.structures.AlgorithmID;
080 import iaik.cms.IaikProvider;
081 import iaik.cms.SecurityProvider;
082 import iaik.cms.Utils;
083 import iaik.x509.X509Certificate;
084
085 /**
086 * Some utilities for the ECC demos.
087 */
088 public class ECCDemoUtil {
089
090 /**
091 * ECC supporting CMS SecurityProvider.
092 */
093 private static IaikProvider iaikEccProvider_;
094
095 /**
096 * Version of the IAIK ECCelerate provider; if used.
097 */
098 private static Double eccelerateVersion_ = null;
099
100
101 /**
102 * Installs an ECC supporting IAIK SecurityProvider. Depending on its presence in
103 * the classpath, either the new (ECCelerate) or old (IAIK-ECC) library is used.
104 *
105 * @return the ECC supporting IAIK SecurityProvider
106 *
107 * @throws Exception if the IAIK ECC Provider cannot be installed
108 */
109 public static IaikProvider installIaikEccProvider() throws Exception {
110 if (iaikEccProvider_ == null) {
111 IaikProvider iaikEccProvider = null;
112
113 try {
114 iaikEccProvider = installIaikEccelerateProvider();
115 } catch (Throwable t) {
116 // ignore; try old IAIK-ECC library
117 }
118
119 if (iaikEccProvider == null) {
120 if (Utils.isClassAvailable("iaik.security.ecc.provider.ECCProvider")) {
121 // old IAIK-ECC library
122 iaikEccProvider = (IaikProvider)Class.forName("iaik.cms.ecc.IaikEccProvider").newInstance();
123
124 try {
125 // set default domain parameter encoding as OID
126 Class ecdsaParameterCl = null;
127 ecdsaParameterCl = Class.forName("iaik.security.ecc.ecdsa.ECDSAParameter");
128 Method method = ecdsaParameterCl.getDeclaredMethod("setDefaultOIDEncoding", new Class[] {boolean.class});
129 method.invoke(ecdsaParameterCl, new Object[] { Boolean.TRUE });
130 } catch (Throwable t) {
131 System.out.println("Warning: could not set oid as default demoan parameter encoding for IAIK_ECC: " + t.toString());
132 }
133 }
134 }
135 if (iaikEccProvider == null) {
136 throw new Exception("Cannot install ECC SecurityProvider!");
137 }
138 iaikEccProvider_ = iaikEccProvider;
139 }
140 SecurityProvider.setSecurityProvider(iaikEccProvider_);
141 return iaikEccProvider_;
142 }
143
144 /**
145 * Installs the IAIK ECCelerate SecurityProvider.
146 *
147 * @return the IAIK ECCelerate SecurityProvider
148 *
149 * @throws Exception if the provider cannot be installed
150 */
151 public static IaikProvider installIaikEccelerateProvider() throws Exception {
152 if ((iaikEccProvider_ == null) ||
153 (!"iaik.cms.ecc.ECCelerateProvider".equals(iaikEccProvider_.getClass().getName()))) {
154 IaikProvider iaikEccProvider = null;
155 Class eccelerateProviderCl = null;
156 try {
157 eccelerateProviderCl = Class.forName("iaik.security.ec.provider.ECCelerate");
158 } catch (Throwable t) {
159 throw new NoSuchProviderException("Ecclerate provider not available: " + t.toString());
160 }
161
162 // new IAIK-ECC library
163 Provider eccProvider = (Provider)eccelerateProviderCl.newInstance();
164 Class iaikCmsEccelerateProviderCl = null;
165 try {
166 iaikCmsEccelerateProviderCl = Class.forName("iaik.cms.ecc.ECCelerateProvider");
167 } catch (Throwable t) {
168 throw new NoSuchProviderException("iaik.cms.ecc.ECCelerateProvider not available: " + t.toString());
169 }
170 Security.insertProviderAt(eccProvider, 1);
171 iaikEccProvider = (IaikProvider)iaikCmsEccelerateProviderCl.newInstance();
172 try {
173 // for the demos we disable SP80057 security strength recommendation checks
174 Method[] methods = eccelerateProviderCl.getDeclaredMethods();
175 Method method = eccelerateProviderCl.getDeclaredMethod("enforceSP80057Recommendations", new Class[] {boolean.class});
176 method.invoke(eccelerateProviderCl, new Object[] { Boolean.FALSE });
177 } catch (Throwable t) {
178 // ignore; run with SP80057 recommendations enforced
179 }
180
181 try {
182 // set default compression format to uncompressed
183 Class pointEncodersCl = null;
184 pointEncodersCl = Class.forName("iaik.security.ec.common.PointEncoders");
185 Method method = pointEncodersCl.getDeclaredMethod("setDefaultPointEncoder", new Class[] {pointEncodersCl});
186 Field field = pointEncodersCl.getDeclaredField("UNCOMPRESSED");
187 Object obj = field.get(pointEncodersCl);
188 method.invoke(pointEncodersCl, new Object[] { obj });
189 } catch (Throwable t) {
190 System.out.println("Warning: could not set \"uncompressed\" as default compression format for ECCelerate: " + t.toString());
191 }
192 try {
193 // set default domain parameter encoding as OID
194 Class ecParameterSpecCl = null;
195 ecParameterSpecCl = Class.forName("iaik.security.ec.common.ECParameterSpec");
196 Method method = ecParameterSpecCl.getDeclaredMethod("setDefaultOIDEncoding", new Class[] {boolean.class});
197 method.invoke(ecParameterSpecCl, new Object[] { Boolean.TRUE });
198 } catch (Throwable t) {
199 System.out.println("Warning: could not set oid as default demoan parameter encoding for ECCelerate: " + t.toString());
200 }
201
202 iaikEccProvider_ = iaikEccProvider;
203 }
204 SecurityProvider.setSecurityProvider(iaikEccProvider_);
205 return iaikEccProvider_;
206 }
207
208 /**
209 * Gets the version of the IAIK ECCelerate provider (if used).
210 *
211 * @return the version of the IAIK ECCelerate provider or -1 if
212 * IAIK ECCelerate is not used
213 */
214 public static double getECCelerateVersion() {
215 double version = -1;
216 if (eccelerateVersion_ != null) {
217 version = eccelerateVersion_.doubleValue();
218 } else {
219 SecurityProvider iaikEccProvider = SecurityProvider.getSecurityProvider();
220 if ("iaik.cms.ecc.ECCelerateProvider".equals(iaikEccProvider.getClass().getName())) {
221 Provider eccelerate = Security.getProvider("IAIK ECCelerate");
222 if (eccelerate != null) {
223 version = eccelerate.getVersion();
224 version = 6.2;
225 eccelerateVersion_ = new Double(version);
226 }
227 }
228 }
229 return version;
230 }
231
232 /**
233 * Creates an EC AlgorithmParameterSpec for the given curve name.
234 *
235 * @param curveName the name of the curve
236 *
237 * @return the AlgorithmParameterSpec
238 *
239 * @throws InvalidParameterSpecException if no AlgorithmParameterSpec for the given curve name is
240 * available or cannot be created
241 */
242 public static AlgorithmParameterSpec createParamSpec(String curveName) throws InvalidParameterSpecException {
243 AlgorithmParameterSpec paramSpec = null;
244 SecurityProvider provider = SecurityProvider.getSecurityProvider();
245 paramSpec = provider.getEllipticCurveParameterSpec(curveName);
246 return paramSpec;
247 }
248
249 /**
250 * Signs the given certificate with deterministic generation of parameter k (if supported).
251 *
252 *
253 * @param cert the certificate to be signed
254 * @param algorithm the signature algorithm
255 * @param issuerPK the issuer private key
256 * @throws NoSuchAlgorithmException
257 * @throws CertificateException
258 * @throws InvalidKeyException
259 *
260 */
261 public static void signCertificate(X509Certificate cert, AlgorithmID algorithm, PrivateKey issuerPK)
262 throws InvalidKeyException, CertificateException, NoSuchAlgorithmException {
263 boolean eccelerateAvailable = true;
264 try {
265 installIaikEccelerateProvider();
266 } catch (Exception e) {
267 eccelerateAvailable = false;
268 }
269 if (eccelerateAvailable) {
270 String providerName = "IAIK ECCelerate";
271 if (algorithm.getName().startsWith("ecdsa")) {
272 // RFC 8550 recommends to use deterministic signing for ECDSA;
273 // we create a DeterministicSigning AlgorithmParameterSpec object using reflection here;
274 // generally we could simply use the default constructor:
275 // DeterministicSigning deterministicSigning = new DeterministicSigning();
276
277 AlgorithmParameterSpec deterministicSigning = null;
278 try {
279 Class deterministicSigningCl = Class.forName("iaik.security.ec.ecdsa.DeterministicSigning");
280 Constructor defaultConstructor = deterministicSigningCl.getConstructor(new Class[] { });
281 deterministicSigning = (AlgorithmParameterSpec)defaultConstructor.newInstance(new Object[] { });
282 } catch (Exception e) {
283 // ignore; deterministic signing not available; sign in conventional way
284 }
285 try {
286 cert.sign(algorithm, issuerPK, deterministicSigning, providerName);
287 } catch (InvalidAlgorithmParameterException e) {
288 throw new CertificateException("Error when deterministic signing: " + e.toString());
289 }
290
291 }
292 } else {
293 cert.sign(algorithm, issuerPK);
294 }
295 }
296
297
298 /**
299 * Gets the version number of the current JDK.
300 *
301 * @return the JDK version number
302 */
303 static public String getJDKVersion() {
304 return (String)System.getProperties().get("java.version");
305 }
306
307 }
308
309