Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Bug 1670835 Crypto Policy Support needs to be updated with disable/en…
…able support

Policy update

Current state of the nss policy system:

The initial policy patch focused on getting policy working well in handling ssl. The policy infrastructure used two existing NSS infrastructure:
    1) Algorithm policies tied the OIDS and
    2) the ssl policy constraints first created to handle export policy restrictions.
To make loadable policies work, we added a couple of new things:
   1) a policy parser to the secmod infrastructure which allows us to set algorithm policies based on a config file. This file had two sections: disallow= and allow=. Disallow turned off policy bits, and allow turned them on. Disallow was always parsed first, so you could very strictly control your policy map by saying disallow=all allow={exclusive list of allowed algorithms}
   2) a new NSS_Option() value that allowed the policy parser to set integer values (like minimum tls version) based on the data in the policy parser.
   3) SSL code which is run at ssl_init time that reads the algorithm policies and maps the results to SSL policies.

The resulting loaded policy code, in general, sets the boundaries of what it possible, actually enable/disable of ssl cipher suites are still under program control, and the builtin NSS default values. The only consession to configuration is if a cipher is disallowed by policy, it is also disabled. Allowing a cipher suite by policy that wasn't already enabled, however, doesn't enable that policy by default. Inside the policy restrictions, applications can still make their own decisions on configuration and preference.

At the time the policy system was designed, there were 3 additional features, which were designed, but not specified: disable, enable, and lock.

disable and enable work just like disallow and allow, except the specify what the default settings are. This would allow the policy file to change the underlying default in the case where the application doesn't try to configure ssl on it's own.

lock would make either the policy or configuration 'locked' meaning once the lock has been executed, no further changes to those configurations would be allowed.

What is needed:

We have a need for the following additional features:

1) we want to turn more of the sha-1 hash function off by default. We still need sha-1 digest because it's used in many non-secure cases, but we do want to disable more sha-1 signature usage. Currently only CERT-SIGNATURE and various hmac usages in SSL ciphers can be controlled by policy. We want to disallow a greater range of signature (that is signature use in general).

2) we want to disable more ciphers by default, but need a way to have certain policies (like LEGACY) turn them back on, so that our shipped system is more secure by default.

What this patch provides:

1) A new policy flag NSS_USE_ALG_IN_ANY_SIGNATURE was added. The cryptohi code which exports the NSS sign/verify high level code now checks the hash and signing algorithm against this new policy flag and fails if the policy isn't available.
New key words were added to the policy parser for 'all-signature', which implies all signature flags at once, and 'signature', which maps to NSS_USE_ANY_SIGNATURE. NOTE: disable=all/signature and disable=all/all-signature are effective equivalent because cert-signatures eventually call the low level signature functions, but disable=all allow=rsa-pss/all-signature and disable=all allow=rsa-pss/signature are different in that the latter allows all rsa-pss signature and the latter allows rsa-pss signatures, but no on certificates (or on smime in the future)
Also new keywords were added for rsa-pkcs, rsa-pss, and ecdsa for signature algorithms (along with dsa).

2) This patch implements disable and enable. These functions only work on SSL configuration. In the future SMIME/CMS configuration could also be added. Because the policy system is parsed and handled by NSS, and SSL configuration is handled in SSL, we use the same Apply code we used to apply ssl policy to set the inital configuration. The configured enable/disable state is configured in the ALGORTHIM policy system, where one bit says the enable/disable value is active and another bit which gives it's state.

3) two locks have been implented, policy-lock and ssl-lock. These are specified in the parser as flags (flags=policy-lock,ssl-lock). The policy locks all the policy changes: ssl_policy, algorithm policy, and options. It is implemented by two new exported functions: NSS_IsPolicyLocked() and NSS_LockPolicy(). The first allows applications to test if the policy is locked without having to try changing the policy. The various policy set functions check the NSS_IsPolicyLocked() function and returns SEC_ERROR_POLICY_LOCK if it's true.
 The ssl-lock changes the state of the policy to locked, and the state cannot be changed back without shutting down NSS. The second is implemented by setting a new Option called NSS_DEFAULT_LOCKS and the NSS_DEFAULT_SSL_LOCK flag. The idea is we can add an SMIME lock in the future. SSL checks the NSS_DEFAULT_SSL_LOCK flag before trying to set the cipher suite value, and blocks the change if it's set.

4) sslpolicy tests were updated to test the enable, disable, flags=policy-lock, flags=ssl-lock and the new signature primitives.

5) policy tests were updated to be able to run standalone (like all the other all.sh tests), as well as new tests to detect when no signing algorithms have been enabled.


What is not in the patch

1) S/MIME signature policy has been defined for a while, but never hooked up.
2) S/MIME export policy needs to be connected back to the algorithm policy system just like the ssl cipher suites already are.
3) S/MIME default configuration needs to be connected back to the policy system.
4) ECC Curve policy  needs to be hooked up with the signature policy (probably should create a generic 'key meets policy' function and have every call it).

Differential Revision: https://phabricator.services.mozilla.com/D93697
  • Loading branch information
rjrelyea committed Oct 23, 2020
2 parents ec5afba + 7dfc0e1 commit 4c88c8e
Show file tree
Hide file tree
Showing 21 changed files with 614 additions and 138 deletions.
6 changes: 6 additions & 0 deletions automation/abi-check/expected-report-libnssutil3.so.txt
@@ -0,0 +1,6 @@

2 Added functions:

[A] 'function PRBool NSS_IsPolicyLocked()' {NSS_IsPolicyLocked@@NSSUTIL_3.59}
[A] 'function void NSS_LockPolicy()' {NSS_LockPolicy@@NSSUTIL_3.59}

50 changes: 50 additions & 0 deletions gtests/mozpkix_gtest/pkixcert_signature_algorithm_tests.cpp
Expand Up @@ -7,9 +7,55 @@

#include "mozpkix/pkixder.h"

#include "secoid.h"

using namespace mozilla::pkix;
using namespace mozilla::pkix::test;

/* These tests generate invalid certificates on the fly, We want to test
* validation of those certificates, not the generation, so we
* need to temporarily allow disallowed signature policies before
* we do the actual certificate or ocsp signing
*/
class HashAlgorithmPolicies
{
static const int numberOfHashes = 4; /* sigh */
static const SECOidTag hashOids[numberOfHashes];

PRUint32 savedPolicy[numberOfHashes];

public:
void EnableHashSignaturePolicy(void);
void RestoreHashSignaturePolicy(void);
};

const SECOidTag HashAlgorithmPolicies::hashOids[numberOfHashes] = {
SEC_OID_MD2,
SEC_OID_MD4,
SEC_OID_MD5,
SEC_OID_SHA1 };

void
HashAlgorithmPolicies::EnableHashSignaturePolicy(void)
{
for (int i=0;i < numberOfHashes; i++) {
ASSERT_EQ(SECSuccess,
NSS_GetAlgorithmPolicy(hashOids[i], &savedPolicy[i]));
ASSERT_EQ(SECSuccess,
NSS_SetAlgorithmPolicy(hashOids[i], NSS_USE_ALG_IN_SIGNATURE, 0));
}
}

void
HashAlgorithmPolicies::RestoreHashSignaturePolicy(void)
{
for (int i=0;i < numberOfHashes; i++) {
ASSERT_EQ(SECSuccess,
NSS_SetAlgorithmPolicy(hashOids[i], savedPolicy[i],
NSS_USE_ALG_IN_SIGNATURE));
}
}

static ByteString
CreateCert(const char* issuerCN,
const char* subjectCN,
Expand All @@ -35,16 +81,20 @@ CreateCert(const char* issuerCN,
}

ScopedTestKeyPair reusedKey(CloneReusedKeyPair());
HashAlgorithmPolicies policies;
policies.EnableHashSignaturePolicy();
ByteString certDER(CreateEncodedCertificate(v3, signatureAlgorithm,
serialNumber, issuerDER,
oneDayBeforeNow, oneDayAfterNow,
subjectDER, *reusedKey,
extensions, *reusedKey,
signatureAlgorithm));
policies.RestoreHashSignaturePolicy();
EXPECT_FALSE(ENCODING_FAILED(certDER));
return certDER;
}


class AlgorithmTestsTrustDomain final : public DefaultCryptoTrustDomain
{
public:
Expand Down
20 changes: 20 additions & 0 deletions gtests/mozpkix_gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp
Expand Up @@ -26,6 +26,8 @@

#include "mozpkix/pkixder.h"

#include "secoid.h"

using namespace mozilla::pkix;
using namespace mozilla::pkix::test;

Expand Down Expand Up @@ -338,6 +340,12 @@ TEST_F(pkixocsp_VerifyEncodedResponse_successful, unknown)
TEST_F(pkixocsp_VerifyEncodedResponse_successful,
good_unsupportedSignatureAlgorithm)
{
PRUint32 policyMd5;
ASSERT_EQ(SECSuccess,NSS_GetAlgorithmPolicy(SEC_OID_MD5, &policyMd5));

/* our encode won't work if MD5 isn't allowed by policy */
ASSERT_EQ(SECSuccess,
NSS_SetAlgorithmPolicy(SEC_OID_MD5, NSS_USE_ALG_IN_SIGNATURE, 0));
ByteString responseString(
CreateEncodedOCSPSuccessfulResponse(
OCSPResponseContext::good, *endEntityCertID, byKey,
Expand All @@ -347,6 +355,9 @@ TEST_F(pkixocsp_VerifyEncodedResponse_successful,
Input response;
ASSERT_EQ(Success,
response.Init(responseString.data(), responseString.length()));
/* now restore the existing policy */
ASSERT_EQ(SECSuccess,
NSS_SetAlgorithmPolicy(SEC_OID_MD5, policyMd5, NSS_USE_ALG_IN_SIGNATURE));
bool expired;
ASSERT_EQ(Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED,
VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID,
Expand Down Expand Up @@ -930,14 +941,23 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,
// Note that the algorithm ID (md5WithRSAEncryption) identifies the signature
// algorithm that will be used to sign the certificate that issues the OCSP
// responses, not the responses themselves.
PRUint32 policyMd5;
ASSERT_EQ(SECSuccess,NSS_GetAlgorithmPolicy(SEC_OID_MD5, &policyMd5));

/* our encode won't work if MD5 isn't allowed by policy */
ASSERT_EQ(SECSuccess,
NSS_SetAlgorithmPolicy(SEC_OID_MD5, NSS_USE_ALG_IN_SIGNATURE, 0));
ByteString responseString(
CreateEncodedIndirectOCSPSuccessfulResponse(
"good_indirect_unsupportedSignatureAlgorithm",
OCSPResponseContext::good, byKey,
md5WithRSAEncryption()));
Input response;
/* now restore the existing policy */
ASSERT_EQ(Success,
response.Init(responseString.data(), responseString.length()));
ASSERT_EQ(SECSuccess,
NSS_SetAlgorithmPolicy(SEC_OID_MD5, policyMd5, NSS_USE_ALG_IN_SIGNATURE));
bool expired;
ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT,
VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
Expand Down
3 changes: 3 additions & 0 deletions lib/cryptohi/keyi.h
Expand Up @@ -17,6 +17,9 @@ KeyType seckey_GetKeyType(SECOidTag pubKeyOid);
SECStatus sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg,
const SECItem *param, SECOidTag *encalg, SECOidTag *hashalg);

/* just get the 'encryption' oid from the combined signature oid */
SECOidTag sec_GetEncAlgFromSigAlg(SECOidTag sigAlg);

/* extract the RSA-PSS hash algorithms and salt length from
* parameters, taking into account of the default implications.
*
Expand Down
35 changes: 33 additions & 2 deletions lib/cryptohi/secsign.c
Expand Up @@ -31,6 +31,7 @@ sgn_NewContext(SECOidTag alg, SECItem *params, SECKEYPrivateKey *key)
SGNContext *cx;
SECOidTag hashalg, signalg;
KeyType keyType;
PRUint32 policyFlags;
SECStatus rv;

/* OK, map a PKCS #7 hash and encrypt algorithm into
Expand All @@ -44,7 +45,7 @@ sgn_NewContext(SECOidTag alg, SECItem *params, SECKEYPrivateKey *key)
rv = sec_DecodeSigAlg(NULL, alg, params, &signalg, &hashalg);
if (rv != SECSuccess) {
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return 0;
return NULL;
}
keyType = seckey_GetKeyType(signalg);

Expand All @@ -53,7 +54,19 @@ sgn_NewContext(SECOidTag alg, SECItem *params, SECKEYPrivateKey *key)
!((key->keyType == dsaKey) && (keyType == fortezzaKey)) &&
!((key->keyType == rsaKey) && (keyType == rsaPssKey))) {
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return 0;
return NULL;
}
/* check the policy on the hash algorithm */
if ((NSS_GetAlgorithmPolicy(hashalg, &policyFlags) == SECFailure) ||
!(policyFlags & NSS_USE_ALG_IN_ANY_SIGNATURE)) {
PORT_SetError(SEC_ERROR_SIGNATURE_ALGORITHM_DISABLED);
return NULL;
}
/* check the policy on the encryption algorithm */
if ((NSS_GetAlgorithmPolicy(signalg, &policyFlags) == SECFailure) ||
!(policyFlags & NSS_USE_ALG_IN_ANY_SIGNATURE)) {
PORT_SetError(SEC_ERROR_SIGNATURE_ALGORITHM_DISABLED);
return NULL;
}

cx = (SGNContext *)PORT_ZAlloc(sizeof(SGNContext));
Expand Down Expand Up @@ -452,9 +465,27 @@ SGN_Digest(SECKEYPrivateKey *privKey,
SECItem digder;
PLArenaPool *arena = 0;
SGNDigestInfo *di = 0;
SECOidTag enctag;
PRUint32 policyFlags;

result->data = 0;

/* check the policy on the hash algorithm */
if ((NSS_GetAlgorithmPolicy(algtag, &policyFlags) == SECFailure) ||
!(policyFlags & NSS_USE_ALG_IN_ANY_SIGNATURE)) {
PORT_SetError(SEC_ERROR_SIGNATURE_ALGORITHM_DISABLED);
return SECFailure;
}
/* check the policy on the encryption algorithm */
enctag = sec_GetEncAlgFromSigAlg(
SEC_GetSignatureAlgorithmOidTag(privKey->keyType, algtag));
if ((enctag == SEC_OID_UNKNOWN) ||
(NSS_GetAlgorithmPolicy(enctag, &policyFlags) == SECFailure) ||
!(policyFlags & NSS_USE_ALG_IN_ANY_SIGNATURE)) {
PORT_SetError(SEC_ERROR_SIGNATURE_ALGORITHM_DISABLED);
return SECFailure;
}

if (privKey->keyType == rsaKey) {

arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
Expand Down
120 changes: 74 additions & 46 deletions lib/cryptohi/secvfy.c
Expand Up @@ -216,6 +216,56 @@ const SEC_ASN1Template hashParameterTemplate[] =
{ 0 }
};

/*
* Get just the encryption algorithm from the signature algorithm
*/
SECOidTag
sec_GetEncAlgFromSigAlg(SECOidTag sigAlg)
{
/* get the "encryption" algorithm */
switch (sigAlg) {
case SEC_OID_PKCS1_RSA_ENCRYPTION:
case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE:
case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE:
case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
return SEC_OID_PKCS1_RSA_ENCRYPTION;
case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
return SEC_OID_PKCS1_RSA_PSS_SIGNATURE;

/* what about normal DSA? */
case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST:
case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST:
case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST:
return SEC_OID_ANSIX9_DSA_SIGNATURE;
case SEC_OID_MISSI_DSS:
case SEC_OID_MISSI_KEA_DSS:
case SEC_OID_MISSI_KEA_DSS_OLD:
case SEC_OID_MISSI_DSS_OLD:
return SEC_OID_MISSI_DSS;
case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
return SEC_OID_ANSIX962_EC_PUBLIC_KEY;
/* we don't implement MD4 hashes */
case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
default:
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
break;
}
return SEC_OID_UNKNOWN;
}

/*
* Pulls the hash algorithm, signing algorithm, and key type out of a
* composite algorithm.
Expand All @@ -229,15 +279,16 @@ const SEC_ASN1Template hashParameterTemplate[] =
*/
SECStatus
sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg,
const SECItem *param, SECOidTag *encalg, SECOidTag *hashalg)
const SECItem *param, SECOidTag *encalgp, SECOidTag *hashalg)
{
int len;
PLArenaPool *arena;
SECStatus rv;
SECItem oid;
SECOidTag encalg;

PR_ASSERT(hashalg != NULL);
PR_ASSERT(encalg != NULL);
PR_ASSERT(encalgp != NULL);

switch (sigAlg) {
/* We probably shouldn't be generating MD2 signatures either */
Expand Down Expand Up @@ -354,52 +405,13 @@ sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg,
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return SECFailure;
}
/* get the "encryption" algorithm */
switch (sigAlg) {
case SEC_OID_PKCS1_RSA_ENCRYPTION:
case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE:
case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE:
case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
*encalg = SEC_OID_PKCS1_RSA_ENCRYPTION;
break;
case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
*encalg = SEC_OID_PKCS1_RSA_PSS_SIGNATURE;
break;

/* what about normal DSA? */
case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST:
case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST:
case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST:
*encalg = SEC_OID_ANSIX9_DSA_SIGNATURE;
break;
case SEC_OID_MISSI_DSS:
case SEC_OID_MISSI_KEA_DSS:
case SEC_OID_MISSI_KEA_DSS_OLD:
case SEC_OID_MISSI_DSS_OLD:
*encalg = SEC_OID_MISSI_DSS;
break;
case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
*encalg = SEC_OID_ANSIX962_EC_PUBLIC_KEY;
break;
/* we don't implement MD4 hashes */
case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
default:
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return SECFailure;
encalg = sec_GetEncAlgFromSigAlg(sigAlg);
if (encalg == SEC_OID_UNKNOWN) {
return SECFailure;
}
*encalgp = encalg;

return SECSuccess;
}

Expand All @@ -423,6 +435,7 @@ vfy_CreateContext(const SECKEYPublicKey *key, const SECItem *sig,
SECStatus rv;
unsigned int sigLen;
KeyType type;
PRUint32 policyFlags;

/* make sure the encryption algorithm matches the key type */
/* RSA-PSS algorithm can be used with both rsaKey and rsaPssKey */
Expand All @@ -433,6 +446,13 @@ vfy_CreateContext(const SECKEYPublicKey *key, const SECItem *sig,
return NULL;
}

/* check the policy on the encryption algorithm */
if ((NSS_GetAlgorithmPolicy(encAlg, &policyFlags) == SECFailure) ||
!(policyFlags & NSS_USE_ALG_IN_ANY_SIGNATURE)) {
PORT_SetError(SEC_ERROR_SIGNATURE_ALGORITHM_DISABLED);
return NULL;
}

cx = (VFYContext *)PORT_ZAlloc(sizeof(VFYContext));
if (cx == NULL) {
goto loser;
Expand Down Expand Up @@ -493,6 +513,14 @@ vfy_CreateContext(const SECKEYPublicKey *key, const SECItem *sig,
/* error set by HASH_GetHashTypeByOidTag */
goto loser;
}
/* check the policy on the hash algorithm. Do this after
* the rsa decode because some uses of this function get hash implicitly
* from the RSA signature itself. */
if ((NSS_GetAlgorithmPolicy(cx->hashAlg, &policyFlags) == SECFailure) ||
!(policyFlags & NSS_USE_ALG_IN_ANY_SIGNATURE)) {
PORT_SetError(SEC_ERROR_SIGNATURE_ALGORITHM_DISABLED);
goto loser;
}

if (hash) {
*hash = cx->hashAlg;
Expand Down
2 changes: 2 additions & 0 deletions lib/nss/nss.h
Expand Up @@ -299,6 +299,8 @@ SECStatus NSS_UnregisterShutdown(NSS_ShutdownFunc sFunc, void *appData);
* old NSS versions. This option might be removed in the future NSS
* releases; don't rely on it. */
#define __NSS_PKCS12_DECODE_FORCE_UNICODE 0x00c
#define NSS_DEFAULT_LOCKS 0x00d /* lock default values */
#define NSS_DEFAULT_SSL_LOCK 1 /* lock the ssl default values */

/*
* Set and get global options for the NSS library.
Expand Down

0 comments on commit 4c88c8e

Please sign in to comment.