Skip to content

Commit

Permalink
Fix loading of CryptoManager in JSSLoader scenario
Browse files Browse the repository at this point in the history
When using JSSLoader to initialize JSSProvider from the java.security
list, sometimes CryptoManager.getInstance() will fail. Usually this is
because instance is still null, even though

    Security.getProvider("Mozilla-JSS") != null

The error message will usually be something like:

    FINE: CryptoManager: loading JSS library
    FINE: CryptoManager: loaded JSS library from java.library.path
    Exception in thread "main" org.mozilla.jss.NotInitializedException
           at org.mozilla.jss.CryptoManager.getInstance(CryptoManager.java:365)
           at org.mozilla.jss.tests.SigTest.main(SigTest.java:52)

Allow JSSLoader to return the new CryptoManager object, let JSSProvider
store it, so that in this case, CryptoManager.getInstance() will return
an initialized instance.

Signed-off-by: Alexander Scheel <[email protected]>
  • Loading branch information
cipherboy committed Jun 24, 2020
1 parent 20a1585 commit 5c6cef6
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 28 deletions.
63 changes: 43 additions & 20 deletions org/mozilla/jss/CryptoManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -340,31 +340,54 @@ protected CryptoManager() {
* called.
* @return CryptoManager instance.
*/
public synchronized static CryptoManager getInstance()
public static CryptoManager getInstance()
throws NotInitializedException
{
if (instance == null) {
/* Java has lazy-loading Security providers; until a provider
* is requested, it won't be loaded. This means we could've
* initialized the CryptoManager via the JSSLoader but we won't
* know about it until it is explicitly requested.
*
* This breaks tests looking to configure a file-based password
* handler: if the very first call is to getInstance(...) instead
* of a Provider call, we'd fail.
*
* Try to get the Mozilla-JSS provider by name before reporting
* that we're not initialized.
*/
if (Security.getProvider("Mozilla-JSS") != null) {
if (instance != null) {
return instance;
}
synchronized (CryptoManager.class) {
if (instance != null) {
return instance;
}
}

/* Java has lazy-loading Security providers; until a provider
* is requested, it won't be loaded. This means we could've
* initialized the CryptoManager via the JSSLoader but we won't
* know about it until it is explicitly requested.
*
* This breaks tests looking to configure a file-based password
* handler: if the very first call is to getInstance(...) instead
* of a Provider call, we'd fail.
*
* Try to get the Mozilla-JSS provider by name before reporting
* that we're not initialized.
*
* However, in order for the JSSProvider to load, we need to
* release our lock on CryptoManager (and in particular, on
* CryptoManager.instance).
*/
java.security.Provider p = Security.getProvider("Mozilla-JSS");

synchronized (CryptoManager.class) {
// When instance is properly configured, use that.
if (instance != null) {
return instance;
}

// Otherwise, work around this by looking at what JSSProvider
// created.
if (p instanceof JSSProvider) {
JSSProvider jssProvider = (JSSProvider) p;
assert jssProvider.getCryptoManager() != null;

throw new NotInitializedException();
if (instance == null) {
instance = jssProvider.getCryptoManager();
}

return instance;
}
}
return instance;

throw new NotInitializedException();
}

/**
Expand Down
11 changes: 6 additions & 5 deletions org/mozilla/jss/JSSLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,25 +92,24 @@ public static boolean loaded() {
/**
* Initialize JSS from the specified path to a configuration file.
*/
public static void init(String config_path) throws Exception {
public static CryptoManager init(String config_path) throws Exception {
if (config_path == null) {
String msg = "Please specify the path to the JSS configuration ";
msg += "file in the java.security provider list.";
throw new NullPointerException(msg);
}

try (FileInputStream fistream = new FileInputStream(config_path)) {
init(fistream);
return;
return init(fistream);
}
}

/**
* Initialize JSS from an InputStream.
*/
public static void init(InputStream istream) throws Exception {
public static CryptoManager init(InputStream istream) throws Exception {
if (loaded()) {
return;
return CryptoManager.getInstance();
}

if (istream == null) {
Expand All @@ -137,6 +136,8 @@ public static void init(InputStream istream) throws Exception {
parsePasswords(config, cm);

parseExperimental(config);

return cm;
}

/**
Expand Down
18 changes: 16 additions & 2 deletions org/mozilla/jss/JSSProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public final class JSSProvider extends java.security.Provider {

private static JSSLoader loader = new JSSLoader();

private static CryptoManager cm;

public JSSProvider() {
this(loader.loaded());
}
Expand All @@ -48,7 +50,7 @@ public JSSProvider(String config_path) throws Exception {
public JSSProvider(InputStream config) throws Exception {
this(false);

loader.init(config);
cm = loader.init(config);
initializeProvider();
}

Expand All @@ -63,7 +65,7 @@ public JSSProvider(InputStream config) throws Exception {
*/
public Provider configure(String arg) {
try {
loader.init(arg);
cm = loader.init(arg);
} catch (NullPointerException npe) {
throw npe;
} catch (Exception e) {
Expand All @@ -75,6 +77,18 @@ public Provider configure(String arg) {
return this;
}

/**
* Return the CryptoManager this instance was initialized with.
*/
public CryptoManager getCryptoManager() {
if (cm == null) {
try {
cm = CryptoManager.getInstance();
} catch (NotInitializedException nie) {}
}
return cm;
}

protected void initializeProvider() {
/////////////////////////////////////////////////////////////
// Signature
Expand Down
1 change: 0 additions & 1 deletion tools/jss.cfg.in
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
nss.config_dir=${NSS_DB_PATH}
nss.cooperate=true
jss.password=${DB_PWD}
jss.experimental.sslengine=true

0 comments on commit 5c6cef6

Please sign in to comment.