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