1 /* 2 * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 25 // common infrastructure for SunPKCS11 tests 26 27 import java.io.BufferedReader; 28 import java.io.ByteArrayOutputStream; 29 import java.io.File; 30 import java.io.IOException; 31 import java.io.InputStream; 32 import java.io.InputStreamReader; 33 import java.io.StringReader; 34 import java.nio.charset.StandardCharsets; 35 import java.nio.file.Files; 36 import java.nio.file.Path; 37 import java.nio.file.Paths; 38 import java.security.AlgorithmParameters; 39 import java.security.InvalidAlgorithmParameterException; 40 import java.security.KeyPairGenerator; 41 import java.security.NoSuchProviderException; 42 import java.security.Policy; 43 import java.security.Provider; 44 import java.security.ProviderException; 45 import java.security.Security; 46 import java.security.spec.ECGenParameterSpec; 47 import java.security.spec.ECParameterSpec; 48 import java.util.ArrayList; 49 import java.util.Arrays; 50 import java.util.HashMap; 51 import java.util.Iterator; 52 import java.util.List; 53 import java.util.Map; 54 import java.util.Optional; 55 import java.util.Properties; 56 import java.util.ServiceConfigurationError; 57 import java.util.ServiceLoader; 58 import java.util.Set; 59 60 import jdk.test.lib.artifacts.Artifact; 61 import jdk.test.lib.artifacts.ArtifactResolver; 62 import jdk.test.lib.artifacts.ArtifactResolverException; 63 64 public abstract class PKCS11Test { 65 66 private boolean enableSM = false; 67 68 static final Properties props = System.getProperties(); 69 70 static final String PKCS11 = "PKCS11"; 71 72 // directory of the test source 73 static final String BASE = System.getProperty("test.src", "."); 74 75 static final char SEP = File.separatorChar; 76 77 private static final String DEFAULT_POLICY = 78 BASE + SEP + ".." + SEP + "policy"; 79 80 // directory corresponding to BASE in the /closed hierarchy 81 static final String CLOSED_BASE; 82 83 static { 84 // hack 85 String absBase = new File(BASE).getAbsolutePath(); 86 int k = absBase.indexOf(SEP + "test" + SEP + "jdk" + SEP); 87 if (k < 0) k = 0; 88 String p1 = absBase.substring(0, k); 89 String p2 = absBase.substring(k); 90 CLOSED_BASE = p1 + "/../closed" + p2; 91 92 // set it as a system property to make it available in policy file 93 System.setProperty("closed.base", CLOSED_BASE); 94 } 95 96 // NSS version info 97 public static enum ECCState { None, Basic, Extended }; 98 static double nss_version = -1; 99 static ECCState nss_ecc_status = ECCState.Extended; 100 101 // The NSS library we need to search for in getNSSLibDir() 102 // Default is "libsoftokn3.so", listed as "softokn3" 103 // The other is "libnss3.so", listed as "nss3". 104 static String nss_library = "softokn3"; 105 106 // NSS versions of each library. It is simplier to keep nss_version 107 // for quick checking for generic testing than many if-else statements. 108 static double softoken3_version = -1; 109 static double nss3_version = -1; 110 static Provider pkcs11; 111 112 // Goes through ServiceLoader instead of Provider.getInstance() since it 113 // works on all platforms 114 static { 115 ServiceLoader sl = ServiceLoader.load(java.security.Provider.class); 116 Iterator<Provider> iter = sl.iterator(); 117 Provider p = null; 118 boolean found = false; 119 while (iter.hasNext()) { 120 try { 121 p = iter.next(); 122 if (p.getName().equals("SunPKCS11")) { 123 found = true; 124 break; 125 } 126 } catch (Exception | ServiceConfigurationError e) { 127 // ignore and move on to the next one 128 } 129 } 130 // Nothing found through ServiceLoader; fall back to reflection 131 if (!found) { 132 try { 133 Class clazz = Class.forName("sun.security.pkcs11.SunPKCS11"); 134 p = (Provider) clazz.newInstance(); 135 } catch (Exception ex) { 136 ex.printStackTrace(); 137 } 138 } 139 pkcs11 = p; 140 } 141 142 /* 143 * Use Solaris SPARC 11.2 or later to avoid an intermittent failure 144 * when running SunPKCS11-Solaris (8044554) 145 */ 146 static boolean isBadSolarisSparc(Provider p) { 147 if ("SunPKCS11-Solaris".equals(p.getName()) && badSolarisSparc) { 148 System.out.println("SunPKCS11-Solaris provider requires " + 149 "Solaris SPARC 11.2 or later, skipping"); 150 return true; 151 } 152 return false; 153 } 154 155 // Return a SunPKCS11 provider configured with the specified config file 156 static Provider getSunPKCS11(String config) throws Exception { 157 if (pkcs11 == null) { 158 throw new NoSuchProviderException("No PKCS11 provider available"); 159 } 160 return pkcs11.configure(config); 161 } 162 163 public abstract void main(Provider p) throws Exception; 164 165 protected boolean skipTest(Provider p) { 166 return false; 167 } 168 169 private void premain(Provider p) throws Exception { 170 if (skipTest(p)) { 171 return; 172 } 173 174 // set a security manager and policy before a test case runs, 175 // and disable them after the test case finished 176 try { 177 if (enableSM) { 178 System.setSecurityManager(new SecurityManager()); 179 } 180 long start = System.currentTimeMillis(); 181 System.out.printf( 182 "Running test with provider %s (security manager %s) ...%n", 183 p.getName(), enableSM ? "enabled" : "disabled"); 184 main(p); 185 long stop = System.currentTimeMillis(); 186 System.out.println("Completed test with provider " + p.getName() + 187 " (" + (stop - start) + " ms)."); 188 } finally { 189 if (enableSM) { 190 System.setSecurityManager(null); 191 } 192 } 193 } 194 195 public static void main(PKCS11Test test) throws Exception { 196 main(test, null); 197 } 198 199 public static void main(PKCS11Test test, String[] args) throws Exception { 200 if (args != null) { 201 if (args.length > 0) { 202 if ("sm".equals(args[0])) { 203 test.enableSM = true; 204 } else { 205 throw new RuntimeException("Unknown Command, use 'sm' as " 206 + "first arguemtn to enable security manager"); 207 } 208 } 209 if (test.enableSM) { 210 System.setProperty("java.security.policy", 211 (args.length > 1) ? BASE + SEP + args[1] 212 : DEFAULT_POLICY); 213 } 214 } 215 216 Provider[] oldProviders = Security.getProviders(); 217 try { 218 System.out.println("Beginning test run " + test.getClass().getName() + "..."); 219 testDefault(test); 220 testNSS(test); 221 testDeimos(test); 222 } finally { 223 // NOTE: Do not place a 'return' in any finally block 224 // as it will suppress exceptions and hide test failures. 225 Provider[] newProviders = Security.getProviders(); 226 boolean found = true; 227 // Do not restore providers if nothing changed. This is especailly 228 // useful for ./Provider/Login.sh, where a SecurityManager exists. 229 if (oldProviders.length == newProviders.length) { 230 found = false; 231 for (int i = 0; i<oldProviders.length; i++) { 232 if (oldProviders[i] != newProviders[i]) { 233 found = true; 234 break; 235 } 236 } 237 } 238 if (found) { 239 for (Provider p: newProviders) { 240 Security.removeProvider(p.getName()); 241 } 242 for (Provider p: oldProviders) { 243 Security.addProvider(p); 244 } 245 } 246 } 247 } 248 249 public static void testDeimos(PKCS11Test test) throws Exception { 250 if (new File("/opt/SUNWconn/lib/libpkcs11.so").isFile() == false || 251 "true".equals(System.getProperty("NO_DEIMOS"))) { 252 return; 253 } 254 String base = getBase(); 255 String p11config = base + SEP + "nss" + SEP + "p11-deimos.txt"; 256 Provider p = getSunPKCS11(p11config); 257 test.premain(p); 258 } 259 260 public static void testDefault(PKCS11Test test) throws Exception { 261 // run test for default configured PKCS11 providers (if any) 262 263 if ("true".equals(System.getProperty("NO_DEFAULT"))) { 264 return; 265 } 266 267 Provider[] providers = Security.getProviders(); 268 for (int i = 0; i < providers.length; i++) { 269 Provider p = providers[i]; 270 if (p.getName().startsWith("SunPKCS11-")) { 271 test.premain(p); 272 } 273 } 274 } 275 276 private static String PKCS11_BASE; 277 static { 278 try { 279 PKCS11_BASE = getBase(); 280 } catch (Exception e) { 281 // ignore 282 } 283 } 284 285 private final static String PKCS11_REL_PATH = "sun/security/pkcs11"; 286 287 public static String getBase() throws Exception { 288 if (PKCS11_BASE != null) { 289 return PKCS11_BASE; 290 } 291 File cwd = new File(System.getProperty("test.src", ".")).getCanonicalFile(); 292 while (true) { 293 File file = new File(cwd, "TEST.ROOT"); 294 if (file.isFile()) { 295 break; 296 } 297 cwd = cwd.getParentFile(); 298 if (cwd == null) { 299 throw new Exception("Test root directory not found"); 300 } 301 } 302 PKCS11_BASE = new File(cwd, PKCS11_REL_PATH.replace('/', SEP)).getAbsolutePath(); 303 return PKCS11_BASE; 304 } 305 306 public static String getNSSLibDir() throws Exception { 307 return getNSSLibDir(nss_library); 308 } 309 310 static String getNSSLibDir(String library) throws Exception { 311 Path libPath = getNSSLibPath(library); 312 if (libPath == null) { 313 return null; 314 } 315 316 String libDir = String.valueOf(libPath.getParent()) + File.separatorChar; 317 System.out.println("nssLibDir: " + libDir); 318 System.setProperty("pkcs11test.nss.libdir", libDir); 319 return libDir; 320 } 321 322 private static Path getNSSLibPath() throws Exception { 323 return getNSSLibPath(nss_library); 324 } 325 326 static Path getNSSLibPath(String library) throws Exception { 327 String osid = getOsId(); 328 String[] nssLibDirs = getNssLibPaths(osid); 329 if (nssLibDirs == null) { 330 System.out.println("Warning: unsupported OS: " + osid 331 + ", please initialize NSS librarys location firstly, skipping test"); 332 return null; 333 } 334 if (nssLibDirs.length == 0) { 335 System.out.println("Warning: NSS not supported on this platform, skipping test"); 336 return null; 337 } 338 339 Path nssLibPath = null; 340 for (String dir : nssLibDirs) { 341 Path libPath = Paths.get(dir).resolve(System.mapLibraryName(library)); 342 if (Files.exists(libPath)) { 343 nssLibPath = libPath; 344 break; 345 } 346 } 347 if (nssLibPath == null) { 348 System.out.println("Warning: can't find NSS librarys on this machine, skipping test"); 349 return null; 350 } 351 return nssLibPath; 352 } 353 354 private static String getOsId() { 355 String osName = props.getProperty("os.name"); 356 if (osName.startsWith("Win")) { 357 osName = "Windows"; 358 } else if (osName.equals("Mac OS X")) { 359 osName = "MacOSX"; 360 } 361 String osid = osName + "-" + props.getProperty("os.arch") + "-" 362 + props.getProperty("sun.arch.data.model"); 363 return osid; 364 } 365 366 static boolean isBadNSSVersion(Provider p) { 367 double nssVersion = getNSSVersion(); 368 if (isNSS(p) && nssVersion >= 3.11 && nssVersion < 3.12) { 369 System.out.println("NSS 3.11 has a DER issue that recent " + 370 "version do not, skipping"); 371 return true; 372 } 373 return false; 374 } 375 376 protected static void safeReload(String lib) throws Exception { 377 try { 378 System.load(lib); 379 } catch (UnsatisfiedLinkError e) { 380 if (e.getMessage().contains("already loaded")) { 381 return; 382 } 383 } 384 } 385 386 static boolean loadNSPR(String libdir) throws Exception { 387 // load NSS softoken dependencies in advance to avoid resolver issues 388 String dir = libdir.endsWith(File.separator) 389 ? libdir 390 : libdir + File.separator; 391 safeReload(dir + System.mapLibraryName("nspr4")); 392 safeReload(dir + System.mapLibraryName("plc4")); 393 safeReload(dir + System.mapLibraryName("plds4")); 394 safeReload(dir + System.mapLibraryName("sqlite3")); 395 safeReload(dir + System.mapLibraryName("nssutil3")); 396 return true; 397 } 398 399 // Check the provider being used is NSS 400 public static boolean isNSS(Provider p) { 401 return p.getName().toUpperCase().equals("SUNPKCS11-NSS"); 402 } 403 404 static double getNSSVersion() { 405 if (nss_version == -1) 406 getNSSInfo(); 407 return nss_version; 408 } 409 410 static ECCState getNSSECC() { 411 if (nss_version == -1) 412 getNSSInfo(); 413 return nss_ecc_status; 414 } 415 416 public static double getLibsoftokn3Version() { 417 if (softoken3_version == -1) 418 return getNSSInfo("softokn3"); 419 return softoken3_version; 420 } 421 422 public static double getLibnss3Version() { 423 if (nss3_version == -1) 424 return getNSSInfo("nss3"); 425 return nss3_version; 426 } 427 428 /* Read the library to find out the verison */ 429 static void getNSSInfo() { 430 getNSSInfo(nss_library); 431 } 432 433 // Try to parse the version for the specified library. 434 // Assuming the library contains either of the following patterns: 435 // $Header: NSS <version> 436 // Version: NSS <version> 437 // Here, <version> stands for NSS version. 438 static double getNSSInfo(String library) { 439 // look for two types of headers in NSS libraries 440 String nssHeader1 = "$Header: NSS"; 441 String nssHeader2 = "Version: NSS"; 442 boolean found = false; 443 String s = null; 444 int i = 0; 445 Path libfile = null; 446 447 if (library.compareTo("softokn3") == 0 && softoken3_version > -1) 448 return softoken3_version; 449 if (library.compareTo("nss3") == 0 && nss3_version > -1) 450 return nss3_version; 451 452 try { 453 libfile = getNSSLibPath(); 454 if (libfile == null) { 455 return 0.0; 456 } 457 try (InputStream is = Files.newInputStream(libfile)) { 458 byte[] data = new byte[1000]; 459 int read = 0; 460 461 while (is.available() > 0) { 462 if (read == 0) { 463 read = is.read(data, 0, 1000); 464 } else { 465 // Prepend last 100 bytes in case the header was split 466 // between the reads. 467 System.arraycopy(data, 900, data, 0, 100); 468 read = 100 + is.read(data, 100, 900); 469 } 470 471 s = new String(data, 0, read, StandardCharsets.US_ASCII); 472 i = s.indexOf(nssHeader1); 473 if (i > 0 || (i = s.indexOf(nssHeader2)) > 0) { 474 found = true; 475 // If the nssHeader is before 920 we can break, otherwise 476 // we may not have the whole header so do another read. If 477 // no bytes are in the stream, that is ok, found is true. 478 if (i < 920) { 479 break; 480 } 481 } 482 } 483 } 484 } catch (Exception e) { 485 e.printStackTrace(); 486 } 487 488 if (!found) { 489 System.out.println("lib" + library + 490 " version not found, set to 0.0: " + libfile); 491 nss_version = 0.0; 492 return nss_version; 493 } 494 495 // the index after whitespace after nssHeader 496 int afterheader = s.indexOf("NSS", i) + 4; 497 String version = String.valueOf(s.charAt(afterheader)); 498 for (char c = s.charAt(++afterheader); 499 c == '.' || (c >= '0' && c <= '9'); 500 c = s.charAt(++afterheader)) { 501 version += c; 502 } 503 504 // If a "dot dot" release, strip the extra dots for double parsing 505 String[] dot = version.split("\\."); 506 if (dot.length > 2) { 507 version = dot[0]+"."+dot[1]; 508 for (int j = 2; dot.length > j; j++) { 509 version += dot[j]; 510 } 511 } 512 513 // Convert to double for easier version value checking 514 try { 515 nss_version = Double.parseDouble(version); 516 } catch (NumberFormatException e) { 517 System.out.println("===== Content start ====="); 518 System.out.println(s); 519 System.out.println("===== Content end ====="); 520 System.out.println("Failed to parse lib" + library + 521 " version. Set to 0.0"); 522 e.printStackTrace(); 523 } 524 525 System.out.print("lib" + library + " version = "+version+". "); 526 527 // Check for ECC 528 if (s.indexOf("Basic") > 0) { 529 nss_ecc_status = ECCState.Basic; 530 System.out.println("ECC Basic."); 531 } else if (s.indexOf("Extended") > 0) { 532 nss_ecc_status = ECCState.Extended; 533 System.out.println("ECC Extended."); 534 } else { 535 System.out.println("ECC None."); 536 } 537 538 if (library.compareTo("softokn3") == 0) { 539 softoken3_version = nss_version; 540 } else if (library.compareTo("nss3") == 0) { 541 nss3_version = nss_version; 542 } 543 544 return nss_version; 545 } 546 547 // Used to set the nss_library file to search for libsoftokn3.so 548 public static void useNSS() { 549 nss_library = "nss3"; 550 } 551 552 public static void testNSS(PKCS11Test test) throws Exception { 553 String libdir = getNSSLibDir(); 554 if (libdir == null) { 555 return; 556 } 557 String base = getBase(); 558 559 if (loadNSPR(libdir) == false) { 560 return; 561 } 562 563 String libfile = libdir + System.mapLibraryName(nss_library); 564 565 String customDBdir = System.getProperty("CUSTOM_DB_DIR"); 566 String dbdir = (customDBdir != null) ? 567 customDBdir : 568 base + SEP + "nss" + SEP + "db"; 569 // NSS always wants forward slashes for the config path 570 dbdir = dbdir.replace('\\', '/'); 571 572 String customConfig = System.getProperty("CUSTOM_P11_CONFIG"); 573 String customConfigName = System.getProperty("CUSTOM_P11_CONFIG_NAME", "p11-nss.txt"); 574 String p11config = (customConfig != null) ? 575 customConfig : 576 base + SEP + "nss" + SEP + customConfigName; 577 578 System.setProperty("pkcs11test.nss.lib", libfile); 579 System.setProperty("pkcs11test.nss.db", dbdir); 580 Provider p = getSunPKCS11(p11config); 581 test.premain(p); 582 } 583 584 // Generate a vector of supported elliptic curves of a given provider 585 static List<ECParameterSpec> getKnownCurves(Provider p) throws Exception { 586 int index; 587 int begin; 588 int end; 589 String curve; 590 591 List<ECParameterSpec> results = new ArrayList<>(); 592 // Get Curves to test from SunEC. 593 String kcProp = Security.getProvider("SunEC"). 594 getProperty("AlgorithmParameters.EC SupportedCurves"); 595 596 if (kcProp == null) { 597 throw new RuntimeException( 598 "\"AlgorithmParameters.EC SupportedCurves property\" not found"); 599 } 600 601 System.out.println("Finding supported curves using list from SunEC\n"); 602 index = 0; 603 for (;;) { 604 // Each set of curve names is enclosed with brackets. 605 begin = kcProp.indexOf('[', index); 606 end = kcProp.indexOf(']', index); 607 if (begin == -1 || end == -1) { 608 break; 609 } 610 611 /* 612 * Each name is separated by a comma. 613 * Just get the first name in the set. 614 */ 615 index = end + 1; 616 begin++; 617 end = kcProp.indexOf(',', begin); 618 if (end == -1) { 619 // Only one name in the set. 620 end = index -1; 621 } 622 623 curve = kcProp.substring(begin, end); 624 getSupportedECParameterSpec(curve, p) 625 .ifPresent(spec -> results.add(spec)); 626 } 627 628 if (results.size() == 0) { 629 throw new RuntimeException("No supported EC curves found"); 630 } 631 632 return results; 633 } 634 635 static Optional<ECParameterSpec> getSupportedECParameterSpec(String curve, 636 Provider p) throws Exception { 637 ECParameterSpec e = getECParameterSpec(p, curve); 638 System.out.print("\t "+ curve + ": "); 639 try { 640 KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", p); 641 kpg.initialize(e); 642 kpg.generateKeyPair(); 643 System.out.println("Supported"); 644 return Optional.of(e); 645 } catch (ProviderException ex) { 646 System.out.println("Unsupported: PKCS11: " + 647 ex.getCause().getMessage()); 648 return Optional.empty(); 649 } catch (InvalidAlgorithmParameterException ex) { 650 System.out.println("Unsupported: Key Length: " + 651 ex.getMessage()); 652 return Optional.empty(); 653 } 654 } 655 656 private static ECParameterSpec getECParameterSpec(Provider p, String name) 657 throws Exception { 658 659 AlgorithmParameters parameters = 660 AlgorithmParameters.getInstance("EC", p); 661 662 parameters.init(new ECGenParameterSpec(name)); 663 664 return parameters.getParameterSpec(ECParameterSpec.class); 665 } 666 667 // Check support for a curve with a provided Vector of EC support 668 boolean checkSupport(List<ECParameterSpec> supportedEC, 669 ECParameterSpec curve) { 670 for (ECParameterSpec ec: supportedEC) { 671 if (ec.equals(curve)) { 672 return true; 673 } 674 } 675 return false; 676 } 677 678 private static Map<String,String[]> osMap; 679 680 // Location of the NSS libraries on each supported platform 681 private static Map<String, String[]> getOsMap() { 682 if (osMap != null) { 683 return osMap; 684 } 685 686 osMap = new HashMap<>(); 687 osMap.put("SunOS-sparc-32", new String[] { "/usr/lib/mps/" }); 688 osMap.put("SunOS-sparcv9-64", new String[] { "/usr/lib/mps/64/" }); 689 osMap.put("SunOS-x86-32", new String[] { "/usr/lib/mps/" }); 690 osMap.put("SunOS-amd64-64", new String[] { "/usr/lib/mps/64/" }); 691 osMap.put("Linux-i386-32", new String[] { 692 "/usr/lib/i386-linux-gnu/", 693 "/usr/lib32/", 694 "/usr/lib/" }); 695 osMap.put("Linux-amd64-64", new String[] { 696 "/usr/lib/x86_64-linux-gnu/", 697 "/usr/lib/x86_64-linux-gnu/nss/", 698 "/usr/lib64/" }); 699 osMap.put("Linux-ppc64-64", new String[] { "/usr/lib64/" }); 700 osMap.put("Linux-ppc64le-64", new String[] { "/usr/lib64/" }); 701 osMap.put("Linux-s390x-64", new String[] { "/usr/lib64/" }); 702 osMap.put("Windows-x86-32", new String[] {}); 703 osMap.put("Windows-amd64-64", new String[] {}); 704 osMap.put("MacOSX-x86_64-64", new String[] {}); 705 osMap.put("Linux-arm-32", new String[] { 706 "/usr/lib/arm-linux-gnueabi/nss/", 707 "/usr/lib/arm-linux-gnueabihf/nss/" }); 708 osMap.put("Linux-aarch64-64", new String[] { 709 "/usr/lib/aarch64-linux-gnu/", 710 "/usr/lib/aarch64-linux-gnu/nss/" }); 711 return osMap; 712 } 713 714 private static String[] getNssLibPaths(String osId) { 715 String[] preferablePaths = getPreferableNssLibPaths(osId); 716 if (preferablePaths.length != 0) { 717 return preferablePaths; 718 } else { 719 return getOsMap().get(osId); 720 } 721 } 722 723 private static String[] getPreferableNssLibPaths(String osId) { 724 List<String> nssLibPaths = new ArrayList<>(); 725 726 String customNssLibPaths = System.getProperty("test.nss.lib.paths"); 727 if (customNssLibPaths == null) { 728 // If custom local NSS lib path is not provided, 729 // try to download NSS libs from artifactory 730 String path = fetchNssLib(osId); 731 if (path != null) { 732 nssLibPaths.add(path); 733 } 734 } else { 735 String[] paths = customNssLibPaths.split(","); 736 for (String path : paths) { 737 if (!path.endsWith(File.separator)) { 738 nssLibPaths.add(path + File.separator); 739 } else { 740 nssLibPaths.add(path); 741 } 742 } 743 } 744 745 return nssLibPaths.toArray(new String[nssLibPaths.size()]); 746 } 747 748 private final static char[] hexDigits = "0123456789abcdef".toCharArray(); 749 750 private static final String distro = distro(); 751 752 static final boolean badSolarisSparc = 753 System.getProperty("os.name").equals("SunOS") && 754 System.getProperty("os.arch").equals("sparcv9") && 755 System.getProperty("os.version").compareTo("5.11") <= 0 && 756 getDistro().compareTo("11.2") < 0; 757 758 public static String toString(byte[] b) { 759 if (b == null) { 760 return "(null)"; 761 } 762 StringBuilder sb = new StringBuilder(b.length * 3); 763 for (int i = 0; i < b.length; i++) { 764 int k = b[i] & 0xff; 765 if (i != 0) { 766 sb.append(':'); 767 } 768 sb.append(hexDigits[k >>> 4]); 769 sb.append(hexDigits[k & 0xf]); 770 } 771 return sb.toString(); 772 } 773 774 public static byte[] parse(String s) { 775 if (s.equals("(null)")) { 776 return null; 777 } 778 try { 779 int n = s.length(); 780 ByteArrayOutputStream out = new ByteArrayOutputStream(n / 3); 781 StringReader r = new StringReader(s); 782 while (true) { 783 int b1 = nextNibble(r); 784 if (b1 < 0) { 785 break; 786 } 787 int b2 = nextNibble(r); 788 if (b2 < 0) { 789 throw new RuntimeException("Invalid string " + s); 790 } 791 int b = (b1 << 4) | b2; 792 out.write(b); 793 } 794 return out.toByteArray(); 795 } catch (IOException e) { 796 throw new RuntimeException(e); 797 } 798 } 799 800 private static int nextNibble(StringReader r) throws IOException { 801 while (true) { 802 int ch = r.read(); 803 if (ch == -1) { 804 return -1; 805 } else if ((ch >= '0') && (ch <= '9')) { 806 return ch - '0'; 807 } else if ((ch >= 'a') && (ch <= 'f')) { 808 return ch - 'a' + 10; 809 } else if ((ch >= 'A') && (ch <= 'F')) { 810 return ch - 'A' + 10; 811 } 812 } 813 } 814 815 <T> T[] concat(T[] a, T[] b) { 816 if ((b == null) || (b.length == 0)) { 817 return a; 818 } 819 T[] r = Arrays.copyOf(a, a.length + b.length); 820 System.arraycopy(b, 0, r, a.length, b.length); 821 return r; 822 } 823 824 /** 825 * Returns supported algorithms of specified type. 826 */ 827 static List<String> getSupportedAlgorithms(String type, String alg, 828 Provider p) { 829 // prepare a list of supported algorithms 830 List<String> algorithms = new ArrayList<>(); 831 Set<Provider.Service> services = p.getServices(); 832 for (Provider.Service service : services) { 833 if (service.getType().equals(type) 834 && service.getAlgorithm().startsWith(alg)) { 835 algorithms.add(service.getAlgorithm()); 836 } 837 } 838 return algorithms; 839 } 840 841 /** 842 * Get the identifier for the operating system distribution 843 */ 844 static String getDistro() { 845 return distro; 846 } 847 848 private static String distro() { 849 if (props.getProperty("os.name").equals("SunOS")) { 850 try (BufferedReader in = 851 new BufferedReader(new InputStreamReader( 852 Runtime.getRuntime().exec("uname -v").getInputStream()))) { 853 854 return in.readLine(); 855 } catch (Exception e) { 856 throw new RuntimeException("Failed to determine distro.", e); 857 } 858 } else { 859 // Not used outside Solaris 860 return null; 861 } 862 } 863 864 static byte[] generateData(int length) { 865 byte data[] = new byte[length]; 866 for (int i=0; i<data.length; i++) { 867 data[i] = (byte) (i % 256); 868 } 869 return data; 870 } 871 872 private static String fetchNssLib(String osId) { 873 switch (osId) { 874 case "Windows-x86-32": 875 return fetchNssLib(WINDOWS_X86.class); 876 877 case "Windows-amd64-64": 878 return fetchNssLib(WINDOWS_X64.class); 879 880 case "MacOSX-x86_64-64": 881 return fetchNssLib(MACOSX_X64.class); 882 883 case "Linux-amd64-64": 884 return fetchNssLib(LINUX_X64.class); 885 886 default: 887 return null; 888 } 889 } 890 891 private static String fetchNssLib(Class<?> clazz) { 892 String path = null; 893 try { 894 path = ArtifactResolver.resolve(clazz).entrySet().stream() 895 .findAny().get().getValue() + File.separator + "nsslib" 896 + File.separator; 897 } catch (ArtifactResolverException e) { 898 Throwable cause = e.getCause(); 899 if (cause == null) { 900 System.out.println("Cannot resolve artifact, " 901 + "please check if JIB jar is present in classpath."); 902 } else { 903 throw new RuntimeException("Fetch artifact failed: " + clazz 904 + "\nPlease make sure the artifact is available."); 905 } 906 } 907 Policy.setPolicy(null); // Clear the policy created by JIB if any 908 return path; 909 } 910 911 @Artifact( 912 organization = "jpg.tests.jdk.nsslib", 913 name = "nsslib-windows_x64", 914 revision = "3.46-VS2017", 915 extension = "zip") 916 private static class WINDOWS_X64 { } 917 918 @Artifact( 919 organization = "jpg.tests.jdk.nsslib", 920 name = "nsslib-windows_x86", 921 revision = "3.46-VS2017", 922 extension = "zip") 923 private static class WINDOWS_X86 { } 924 925 @Artifact( 926 organization = "jpg.tests.jdk.nsslib", 927 name = "nsslib-macosx_x64", 928 revision = "3.46", 929 extension = "zip") 930 private static class MACOSX_X64 { } 931 932 @Artifact( 933 organization = "jpg.tests.jdk.nsslib", 934 name = "nsslib-linux_x64", 935 revision = "3.46", 936 extension = "zip") 937 private static class LINUX_X64 { } 938 }