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