1 /* 2 * Copyright (c) 2003, 2020, 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 // Return a SunPKCS11 provider configured with the specified config file 143 static Provider getSunPKCS11(String config) throws Exception { 144 if (pkcs11 == null) { 145 throw new NoSuchProviderException("No PKCS11 provider available"); 146 } 147 return pkcs11.configure(config); 148 } 149 150 public abstract void main(Provider p) throws Exception; 151 152 protected boolean skipTest(Provider p) { 153 return false; 154 } 155 156 private void premain(Provider p) throws Exception { 157 if (skipTest(p)) { 158 return; 159 } 160 161 // set a security manager and policy before a test case runs, 162 // and disable them after the test case finished 163 try { 164 if (enableSM) { 165 System.setSecurityManager(new SecurityManager()); 166 } 167 long start = System.currentTimeMillis(); 168 System.out.printf( 169 "Running test with provider %s (security manager %s) ...%n", 170 p.getName(), enableSM ? "enabled" : "disabled"); 171 main(p); 172 long stop = System.currentTimeMillis(); 173 System.out.println("Completed test with provider " + p.getName() + 174 " (" + (stop - start) + " ms)."); 175 } finally { 176 if (enableSM) { 177 System.setSecurityManager(null); 178 } 179 } 180 } 181 182 public static void main(PKCS11Test test) throws Exception { 183 main(test, null); 184 } 185 186 public static void main(PKCS11Test test, String[] args) throws Exception { 187 if (args != null) { 188 if (args.length > 0) { 189 if ("sm".equals(args[0])) { 190 test.enableSM = true; 191 } else { 192 throw new RuntimeException("Unknown Command, use 'sm' as " 193 + "first arguemtn to enable security manager"); 194 } 195 } 196 if (test.enableSM) { 197 System.setProperty("java.security.policy", 198 (args.length > 1) ? BASE + SEP + args[1] 199 : DEFAULT_POLICY); 200 } 201 } 202 203 Provider[] oldProviders = Security.getProviders(); 204 try { 205 System.out.println("Beginning test run " + test.getClass().getName() + "..."); 206 testDefault(test); 207 testNSS(test); 208 testDeimos(test); 209 } finally { 210 // NOTE: Do not place a 'return' in any finally block 211 // as it will suppress exceptions and hide test failures. 212 Provider[] newProviders = Security.getProviders(); 213 boolean found = true; 214 // Do not restore providers if nothing changed. This is especailly 215 // useful for ./Provider/Login.sh, where a SecurityManager exists. 216 if (oldProviders.length == newProviders.length) { 217 found = false; 218 for (int i = 0; i<oldProviders.length; i++) { 219 if (oldProviders[i] != newProviders[i]) { 220 found = true; 221 break; 222 } 223 } 224 } 225 if (found) { 226 for (Provider p: newProviders) { 227 Security.removeProvider(p.getName()); 228 } 229 for (Provider p: oldProviders) { 230 Security.addProvider(p); 231 } 232 } 233 } 234 } 235 236 public static void testDeimos(PKCS11Test test) throws Exception { 237 if (new File("/opt/SUNWconn/lib/libpkcs11.so").isFile() == false || 238 "true".equals(System.getProperty("NO_DEIMOS"))) { 239 return; 240 } 241 String base = getBase(); 242 String p11config = base + SEP + "nss" + SEP + "p11-deimos.txt"; 243 Provider p = getSunPKCS11(p11config); 244 test.premain(p); 245 } 246 247 public static void testDefault(PKCS11Test test) throws Exception { 248 // run test for default configured PKCS11 providers (if any) 249 250 if ("true".equals(System.getProperty("NO_DEFAULT"))) { 251 return; 252 } 253 254 Provider[] providers = Security.getProviders(); 255 for (int i = 0; i < providers.length; i++) { 256 Provider p = providers[i]; 257 if (p.getName().startsWith("SunPKCS11-")) { 258 test.premain(p); 259 } 260 } 261 } 262 263 private static String PKCS11_BASE; 264 static { 265 try { 266 PKCS11_BASE = getBase(); 267 } catch (Exception e) { 268 // ignore 269 } 270 } 271 272 private final static String PKCS11_REL_PATH = "sun/security/pkcs11"; 273 274 public static String getBase() throws Exception { 275 if (PKCS11_BASE != null) { 276 return PKCS11_BASE; 277 } 278 File cwd = new File(System.getProperty("test.src", ".")).getCanonicalFile(); 279 while (true) { 280 File file = new File(cwd, "TEST.ROOT"); 281 if (file.isFile()) { 282 break; 283 } 284 cwd = cwd.getParentFile(); 285 if (cwd == null) { 286 throw new Exception("Test root directory not found"); 287 } 288 } 289 PKCS11_BASE = new File(cwd, PKCS11_REL_PATH.replace('/', SEP)).getAbsolutePath(); 290 return PKCS11_BASE; 291 } 292 293 public static String getNSSLibDir() throws Exception { 294 return getNSSLibDir(nss_library); 295 } 296 297 static String getNSSLibDir(String library) throws Exception { 298 Path libPath = getNSSLibPath(library); 299 if (libPath == null) { 300 return null; 301 } 302 303 String libDir = String.valueOf(libPath.getParent()) + File.separatorChar; 304 System.out.println("nssLibDir: " + libDir); 305 System.setProperty("pkcs11test.nss.libdir", libDir); 306 return libDir; 307 } 308 309 private static Path getNSSLibPath() throws Exception { 310 return getNSSLibPath(nss_library); 311 } 312 313 static Path getNSSLibPath(String library) throws Exception { 314 String osid = getOsId(); 315 String[] nssLibDirs = getNssLibPaths(osid); 316 if (nssLibDirs == null) { 317 System.out.println("Warning: unsupported OS: " + osid 318 + ", please initialize NSS librarys location firstly, skipping test"); 319 return null; 320 } 321 if (nssLibDirs.length == 0) { 322 System.out.println("Warning: NSS not supported on this platform, skipping test"); 323 return null; 324 } 325 326 Path nssLibPath = null; 327 for (String dir : nssLibDirs) { 328 Path libPath = Paths.get(dir).resolve(System.mapLibraryName(library)); 329 if (Files.exists(libPath)) { 330 nssLibPath = libPath; 331 break; 332 } 333 } 334 if (nssLibPath == null) { 335 System.out.println("Warning: can't find NSS librarys on this machine, skipping test"); 336 return null; 337 } 338 return nssLibPath; 339 } 340 341 private static String getOsId() { 342 String osName = props.getProperty("os.name"); 343 if (osName.startsWith("Win")) { 344 osName = "Windows"; 345 } else if (osName.equals("Mac OS X")) { 346 osName = "MacOSX"; 347 } 348 String osid = osName + "-" + props.getProperty("os.arch") + "-" 349 + props.getProperty("sun.arch.data.model"); 350 return osid; 351 } 352 353 static boolean isBadNSSVersion(Provider p) { 354 double nssVersion = getNSSVersion(); 355 if (isNSS(p) && nssVersion >= 3.11 && nssVersion < 3.12) { 356 System.out.println("NSS 3.11 has a DER issue that recent " + 357 "version do not, skipping"); 358 return true; 359 } 360 return false; 361 } 362 363 protected static void safeReload(String lib) throws Exception { 364 try { 365 System.load(lib); 366 } catch (UnsatisfiedLinkError e) { 367 if (e.getMessage().contains("already loaded")) { 368 return; 369 } 370 } 371 } 372 373 static boolean loadNSPR(String libdir) throws Exception { 374 // load NSS softoken dependencies in advance to avoid resolver issues 375 String dir = libdir.endsWith(File.separator) 376 ? libdir 377 : libdir + File.separator; 378 safeReload(dir + System.mapLibraryName("nspr4")); 379 safeReload(dir + System.mapLibraryName("plc4")); 380 safeReload(dir + System.mapLibraryName("plds4")); 381 safeReload(dir + System.mapLibraryName("sqlite3")); 382 safeReload(dir + System.mapLibraryName("nssutil3")); 383 return true; 384 } 385 386 // Check the provider being used is NSS 387 public static boolean isNSS(Provider p) { 388 return p.getName().toUpperCase().equals("SUNPKCS11-NSS"); 389 } 390 391 static double getNSSVersion() { 392 if (nss_version == -1) 393 getNSSInfo(); 394 return nss_version; 395 } 396 397 static ECCState getNSSECC() { 398 if (nss_version == -1) 399 getNSSInfo(); 400 return nss_ecc_status; 401 } 402 403 public static double getLibsoftokn3Version() { 404 if (softoken3_version == -1) 405 return getNSSInfo("softokn3"); 406 return softoken3_version; 407 } 408 409 public static double getLibnss3Version() { 410 if (nss3_version == -1) 411 return getNSSInfo("nss3"); 412 return nss3_version; 413 } 414 415 /* Read the library to find out the verison */ 416 static void getNSSInfo() { 417 getNSSInfo(nss_library); 418 } 419 420 // Try to parse the version for the specified library. 421 // Assuming the library contains either of the following patterns: 422 // $Header: NSS <version> 423 // Version: NSS <version> 424 // Here, <version> stands for NSS version. 425 static double getNSSInfo(String library) { 426 // look for two types of headers in NSS libraries 427 String nssHeader1 = "$Header: NSS"; 428 String nssHeader2 = "Version: NSS"; 429 boolean found = false; 430 String s = null; 431 int i = 0; 432 Path libfile = null; 433 434 if (library.compareTo("softokn3") == 0 && softoken3_version > -1) 435 return softoken3_version; 436 if (library.compareTo("nss3") == 0 && nss3_version > -1) 437 return nss3_version; 438 439 try { 440 libfile = getNSSLibPath(); 441 if (libfile == null) { 442 return 0.0; 443 } 444 try (InputStream is = Files.newInputStream(libfile)) { 445 byte[] data = new byte[1000]; 446 int read = 0; 447 448 while (is.available() > 0) { 449 if (read == 0) { 450 read = is.read(data, 0, 1000); 451 } else { 452 // Prepend last 100 bytes in case the header was split 453 // between the reads. 454 System.arraycopy(data, 900, data, 0, 100); 455 read = 100 + is.read(data, 100, 900); 456 } 457 458 s = new String(data, 0, read, StandardCharsets.US_ASCII); 459 i = s.indexOf(nssHeader1); 460 if (i > 0 || (i = s.indexOf(nssHeader2)) > 0) { 461 found = true; 462 // If the nssHeader is before 920 we can break, otherwise 463 // we may not have the whole header so do another read. If 464 // no bytes are in the stream, that is ok, found is true. 465 if (i < 920) { 466 break; 467 } 468 } 469 } 470 } 471 } catch (Exception e) { 472 e.printStackTrace(); 473 } 474 475 if (!found) { 476 System.out.println("lib" + library + 477 " version not found, set to 0.0: " + libfile); 478 nss_version = 0.0; 479 return nss_version; 480 } 481 482 // the index after whitespace after nssHeader 483 int afterheader = s.indexOf("NSS", i) + 4; 484 String version = String.valueOf(s.charAt(afterheader)); 485 for (char c = s.charAt(++afterheader); 486 c == '.' || (c >= '0' && c <= '9'); 487 c = s.charAt(++afterheader)) { 488 version += c; 489 } 490 491 // If a "dot dot" release, strip the extra dots for double parsing 492 String[] dot = version.split("\\."); 493 if (dot.length > 2) { 494 version = dot[0]+"."+dot[1]; 495 for (int j = 2; dot.length > j; j++) { 496 version += dot[j]; 497 } 498 } 499 500 // Convert to double for easier version value checking 501 try { 502 nss_version = Double.parseDouble(version); 503 } catch (NumberFormatException e) { 504 System.out.println("===== Content start ====="); 505 System.out.println(s); 506 System.out.println("===== Content end ====="); 507 System.out.println("Failed to parse lib" + library + 508 " version. Set to 0.0"); 509 e.printStackTrace(); 510 } 511 512 System.out.print("lib" + library + " version = "+version+". "); 513 514 // Check for ECC 515 if (s.indexOf("Basic") > 0) { 516 nss_ecc_status = ECCState.Basic; 517 System.out.println("ECC Basic."); 518 } else if (s.indexOf("Extended") > 0) { 519 nss_ecc_status = ECCState.Extended; 520 System.out.println("ECC Extended."); 521 } else { 522 System.out.println("ECC None."); 523 } 524 525 if (library.compareTo("softokn3") == 0) { 526 softoken3_version = nss_version; 527 } else if (library.compareTo("nss3") == 0) { 528 nss3_version = nss_version; 529 } 530 531 return nss_version; 532 } 533 534 // Used to set the nss_library file to search for libsoftokn3.so 535 public static void useNSS() { 536 nss_library = "nss3"; 537 } 538 539 public static void testNSS(PKCS11Test test) throws Exception { 540 String libdir = getNSSLibDir(); 541 if (libdir == null) { 542 return; 543 } 544 String base = getBase(); 545 546 if (loadNSPR(libdir) == false) { 547 return; 548 } 549 550 String libfile = libdir + System.mapLibraryName(nss_library); 551 552 String customDBdir = System.getProperty("CUSTOM_DB_DIR"); 553 String dbdir = (customDBdir != null) ? 554 customDBdir : 555 base + SEP + "nss" + SEP + "db"; 556 // NSS always wants forward slashes for the config path 557 dbdir = dbdir.replace('\\', '/'); 558 559 String customConfig = System.getProperty("CUSTOM_P11_CONFIG"); 560 String customConfigName = System.getProperty("CUSTOM_P11_CONFIG_NAME", "p11-nss.txt"); 561 String p11config = (customConfig != null) ? 562 customConfig : 563 base + SEP + "nss" + SEP + customConfigName; 564 565 System.setProperty("pkcs11test.nss.lib", libfile); 566 System.setProperty("pkcs11test.nss.db", dbdir); 567 Provider p = getSunPKCS11(p11config); 568 test.premain(p); 569 } 570 571 // Generate a vector of supported elliptic curves of a given provider 572 static List<ECParameterSpec> getKnownCurves(Provider p) throws Exception { 573 int index; 574 int begin; 575 int end; 576 String curve; 577 578 List<ECParameterSpec> results = new ArrayList<>(); 579 // Get Curves to test from SunEC. 580 String kcProp = Security.getProvider("SunEC"). 581 getProperty("AlgorithmParameters.EC SupportedCurves"); 582 583 if (kcProp == null) { 584 throw new RuntimeException( 585 "\"AlgorithmParameters.EC SupportedCurves property\" not found"); 586 } 587 588 System.out.println("Finding supported curves using list from SunEC\n"); 589 index = 0; 590 for (;;) { 591 // Each set of curve names is enclosed with brackets. 592 begin = kcProp.indexOf('[', index); 593 end = kcProp.indexOf(']', index); 594 if (begin == -1 || end == -1) { 595 break; 596 } 597 598 /* 599 * Each name is separated by a comma. 600 * Just get the first name in the set. 601 */ 602 index = end + 1; 603 begin++; 604 end = kcProp.indexOf(',', begin); 605 if (end == -1) { 606 // Only one name in the set. 607 end = index -1; 608 } 609 610 curve = kcProp.substring(begin, end); 611 getSupportedECParameterSpec(curve, p) 612 .ifPresent(spec -> results.add(spec)); 613 } 614 615 if (results.size() == 0) { 616 throw new RuntimeException("No supported EC curves found"); 617 } 618 619 return results; 620 } 621 622 static Optional<ECParameterSpec> getSupportedECParameterSpec(String curve, 623 Provider p) throws Exception { 624 ECParameterSpec e = getECParameterSpec(p, curve); 625 System.out.print("\t "+ curve + ": "); 626 try { 627 KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", p); 628 kpg.initialize(e); 629 kpg.generateKeyPair(); 630 System.out.println("Supported"); 631 return Optional.of(e); 632 } catch (ProviderException ex) { 633 System.out.println("Unsupported: PKCS11: " + 634 ex.getCause().getMessage()); 635 return Optional.empty(); 636 } catch (InvalidAlgorithmParameterException ex) { 637 System.out.println("Unsupported: Key Length: " + 638 ex.getMessage()); 639 return Optional.empty(); 640 } 641 } 642 643 private static ECParameterSpec getECParameterSpec(Provider p, String name) 644 throws Exception { 645 646 AlgorithmParameters parameters = 647 AlgorithmParameters.getInstance("EC", p); 648 649 parameters.init(new ECGenParameterSpec(name)); 650 651 return parameters.getParameterSpec(ECParameterSpec.class); 652 } 653 654 // Check support for a curve with a provided Vector of EC support 655 boolean checkSupport(List<ECParameterSpec> supportedEC, 656 ECParameterSpec curve) { 657 for (ECParameterSpec ec: supportedEC) { 658 if (ec.equals(curve)) { 659 return true; 660 } 661 } 662 return false; 663 } 664 665 private static Map<String,String[]> osMap; 666 667 // Location of the NSS libraries on each supported platform 668 private static Map<String, String[]> getOsMap() { 669 if (osMap != null) { 670 return osMap; 671 } 672 673 osMap = new HashMap<>(); 674 osMap.put("Linux-i386-32", new String[] { 675 "/usr/lib/i386-linux-gnu/", 676 "/usr/lib32/", 677 "/usr/lib/" }); 678 osMap.put("Linux-amd64-64", new String[] { 679 "/usr/lib/x86_64-linux-gnu/", 680 "/usr/lib/x86_64-linux-gnu/nss/", 681 "/usr/lib64/" }); 682 osMap.put("Linux-ppc64-64", new String[] { "/usr/lib64/" }); 683 osMap.put("Linux-ppc64le-64", new String[] { "/usr/lib64/" }); 684 osMap.put("Linux-s390x-64", new String[] { "/usr/lib64/" }); 685 osMap.put("Windows-x86-32", new String[] {}); 686 osMap.put("Windows-amd64-64", new String[] {}); 687 osMap.put("MacOSX-x86_64-64", new String[] {}); 688 osMap.put("Linux-arm-32", new String[] { 689 "/usr/lib/arm-linux-gnueabi/nss/", 690 "/usr/lib/arm-linux-gnueabihf/nss/" }); 691 osMap.put("Linux-aarch64-64", new String[] { 692 "/usr/lib/aarch64-linux-gnu/", 693 "/usr/lib/aarch64-linux-gnu/nss/" }); 694 return osMap; 695 } 696 697 private static String[] getNssLibPaths(String osId) { 698 String[] preferablePaths = getPreferableNssLibPaths(osId); 699 if (preferablePaths.length != 0) { 700 return preferablePaths; 701 } else { 702 return getOsMap().get(osId); 703 } 704 } 705 706 private static String[] getPreferableNssLibPaths(String osId) { 707 List<String> nssLibPaths = new ArrayList<>(); 708 709 String customNssLibPaths = System.getProperty("test.nss.lib.paths"); 710 if (customNssLibPaths == null) { 711 // If custom local NSS lib path is not provided, 712 // try to download NSS libs from artifactory 713 String path = fetchNssLib(osId); 714 if (path != null) { 715 nssLibPaths.add(path); 716 } 717 } else { 718 String[] paths = customNssLibPaths.split(","); 719 for (String path : paths) { 720 if (!path.endsWith(File.separator)) { 721 nssLibPaths.add(path + File.separator); 722 } else { 723 nssLibPaths.add(path); 724 } 725 } 726 } 727 728 return nssLibPaths.toArray(new String[nssLibPaths.size()]); 729 } 730 731 private final static char[] hexDigits = "0123456789abcdef".toCharArray(); 732 733 public static String toString(byte[] b) { 734 if (b == null) { 735 return "(null)"; 736 } 737 StringBuilder sb = new StringBuilder(b.length * 3); 738 for (int i = 0; i < b.length; i++) { 739 int k = b[i] & 0xff; 740 if (i != 0) { 741 sb.append(':'); 742 } 743 sb.append(hexDigits[k >>> 4]); 744 sb.append(hexDigits[k & 0xf]); 745 } 746 return sb.toString(); 747 } 748 749 public static byte[] parse(String s) { 750 if (s.equals("(null)")) { 751 return null; 752 } 753 try { 754 int n = s.length(); 755 ByteArrayOutputStream out = new ByteArrayOutputStream(n / 3); 756 StringReader r = new StringReader(s); 757 while (true) { 758 int b1 = nextNibble(r); 759 if (b1 < 0) { 760 break; 761 } 762 int b2 = nextNibble(r); 763 if (b2 < 0) { 764 throw new RuntimeException("Invalid string " + s); 765 } 766 int b = (b1 << 4) | b2; 767 out.write(b); 768 } 769 return out.toByteArray(); 770 } catch (IOException e) { 771 throw new RuntimeException(e); 772 } 773 } 774 775 private static int nextNibble(StringReader r) throws IOException { 776 while (true) { 777 int ch = r.read(); 778 if (ch == -1) { 779 return -1; 780 } else if ((ch >= '0') && (ch <= '9')) { 781 return ch - '0'; 782 } else if ((ch >= 'a') && (ch <= 'f')) { 783 return ch - 'a' + 10; 784 } else if ((ch >= 'A') && (ch <= 'F')) { 785 return ch - 'A' + 10; 786 } 787 } 788 } 789 790 <T> T[] concat(T[] a, T[] b) { 791 if ((b == null) || (b.length == 0)) { 792 return a; 793 } 794 T[] r = Arrays.copyOf(a, a.length + b.length); 795 System.arraycopy(b, 0, r, a.length, b.length); 796 return r; 797 } 798 799 /** 800 * Returns supported algorithms of specified type. 801 */ 802 static List<String> getSupportedAlgorithms(String type, String alg, 803 Provider p) { 804 // prepare a list of supported algorithms 805 List<String> algorithms = new ArrayList<>(); 806 Set<Provider.Service> services = p.getServices(); 807 for (Provider.Service service : services) { 808 if (service.getType().equals(type) 809 && service.getAlgorithm().startsWith(alg)) { 810 algorithms.add(service.getAlgorithm()); 811 } 812 } 813 return algorithms; 814 } 815 816 static byte[] generateData(int length) { 817 byte data[] = new byte[length]; 818 for (int i=0; i<data.length; i++) { 819 data[i] = (byte) (i % 256); 820 } 821 return data; 822 } 823 824 private static String fetchNssLib(String osId) { 825 switch (osId) { 826 case "Windows-x86-32": 827 return fetchNssLib(WINDOWS_X86.class); 828 829 case "Windows-amd64-64": 830 return fetchNssLib(WINDOWS_X64.class); 831 832 case "MacOSX-x86_64-64": 833 return fetchNssLib(MACOSX_X64.class); 834 835 case "Linux-amd64-64": 836 return fetchNssLib(LINUX_X64.class); 837 838 default: 839 return null; 840 } 841 } 842 843 private static String fetchNssLib(Class<?> clazz) { 844 String path = null; 845 try { 846 path = ArtifactResolver.resolve(clazz).entrySet().stream() 847 .findAny().get().getValue() + File.separator + "nsslib" 848 + File.separator; 849 } catch (ArtifactResolverException e) { 850 Throwable cause = e.getCause(); 851 if (cause == null) { 852 System.out.println("Cannot resolve artifact, " 853 + "please check if JIB jar is present in classpath."); 854 } else { 855 throw new RuntimeException("Fetch artifact failed: " + clazz 856 + "\nPlease make sure the artifact is available."); 857 } 858 } 859 Policy.setPolicy(null); // Clear the policy created by JIB if any 860 return path; 861 } 862 863 @Artifact( 864 organization = "jpg.tests.jdk.nsslib", 865 name = "nsslib-windows_x64", 866 revision = "3.46-VS2017", 867 extension = "zip") 868 private static class WINDOWS_X64 { } 869 870 @Artifact( 871 organization = "jpg.tests.jdk.nsslib", 872 name = "nsslib-windows_x86", 873 revision = "3.46-VS2017", 874 extension = "zip") 875 private static class WINDOWS_X86 { } 876 877 @Artifact( 878 organization = "jpg.tests.jdk.nsslib", 879 name = "nsslib-macosx_x64", 880 revision = "3.46", 881 extension = "zip") 882 private static class MACOSX_X64 { } 883 884 @Artifact( 885 organization = "jpg.tests.jdk.nsslib", 886 name = "nsslib-linux_x64", 887 revision = "3.46", 888 extension = "zip") 889 private static class LINUX_X64 { } 890 }