Bug 1026398 - Add support for RSA-OAEP to WebCrypto API. r=bz,dkeeler
☠☠ backed out by 9e77266536d5 ☠ ☠
authorRichard Barnes <rbarnes@mozilla.com>
Thu, 10 Jul 2014 13:44:00 +0200
changeset 215471 5460c4558253ceab47a691c55a80113c3757fe7e
parent 215470 ff281663a545ba282d171e1b6709d2c23b83153c
child 215472 bf3359ddd83119dec45620cdccad414eac85b8ec
push id515
push userraliiev@mozilla.com
push dateMon, 06 Oct 2014 12:51:51 +0000
treeherdermozilla-release@267c7a481bef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz, dkeeler
bugs1026398
milestone33.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1026398 - Add support for RSA-OAEP to WebCrypto API. r=bz,dkeeler
dom/crypto/KeyAlgorithm.cpp
dom/crypto/WebCryptoCommon.h
dom/crypto/WebCryptoTask.cpp
dom/webidl/SubtleCrypto.webidl
security/build/nss.def
--- a/dom/crypto/KeyAlgorithm.cpp
+++ b/dom/crypto/KeyAlgorithm.cpp
@@ -45,16 +45,18 @@ KeyAlgorithm::KeyAlgorithm(nsIGlobalObje
   } else if (mName.EqualsLiteral(WEBCRYPTO_ALG_SHA384)) {
     mMechanism = CKM_SHA384;
   } else if (mName.EqualsLiteral(WEBCRYPTO_ALG_SHA512)) {
     mMechanism = CKM_SHA512;
   } else if (mName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1)) {
     mMechanism = CKM_RSA_PKCS;
   } else if (mName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
     mMechanism = CKM_RSA_PKCS;
+  } else if (mName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
+    mMechanism = CKM_RSA_PKCS_OAEP;
   } else {
     mMechanism = UNKNOWN_CK_MECHANISM;
   }
   // HMAC not handled here, since it requires extra info
 }
 
 KeyAlgorithm::~KeyAlgorithm()
 {
--- a/dom/crypto/WebCryptoCommon.h
+++ b/dom/crypto/WebCryptoCommon.h
@@ -18,16 +18,17 @@
 #define WEBCRYPTO_ALG_AES_GCM       "AES-GCM"
 #define WEBCRYPTO_ALG_SHA1          "SHA-1"
 #define WEBCRYPTO_ALG_SHA256        "SHA-256"
 #define WEBCRYPTO_ALG_SHA384        "SHA-384"
 #define WEBCRYPTO_ALG_SHA512        "SHA-512"
 #define WEBCRYPTO_ALG_HMAC          "HMAC"
 #define WEBCRYPTO_ALG_RSAES_PKCS1   "RSAES-PKCS1-v1_5"
 #define WEBCRYPTO_ALG_RSASSA_PKCS1  "RSASSA-PKCS1-v1_5"
+#define WEBCRYPTO_ALG_RSA_OAEP      "RSA-OAEP"
 
 // WebCrypto key formats
 #define WEBCRYPTO_KEY_FORMAT_RAW    "raw"
 #define WEBCRYPTO_KEY_FORMAT_PKCS8  "pkcs8"
 #define WEBCRYPTO_KEY_FORMAT_SPKI   "spki"
 #define WEBCRYPTO_KEY_FORMAT_JWK    "jwk"
 
 // WebCrypto key types
--- a/dom/crypto/WebCryptoTask.cpp
+++ b/dom/crypto/WebCryptoTask.cpp
@@ -226,17 +226,17 @@ private:
     mResultPromise->MaybeResolve(ret);
   }
 };
 
 class AesTask : public ReturnArrayBufferViewTask
 {
 public:
   AesTask(JSContext* aCx, const ObjectOrString& aAlgorithm,
-          mozilla::dom::CryptoKey& aKey, const CryptoOperationData& aData,
+          CryptoKey& aKey, const CryptoOperationData& aData,
           bool aEncrypt)
     : mSymKey(aKey.GetSymKey())
     , mEncrypt(aEncrypt)
   {
     ATTEMPT_BUFFER_INIT(mData, aData);
 
     nsString algName;
     mEarlyRv = GetAlgorithmName(aCx, aAlgorithm, algName);
@@ -403,17 +403,17 @@ private:
     return rv;
   }
 };
 
 class RsaesPkcs1Task : public ReturnArrayBufferViewTask
 {
 public:
   RsaesPkcs1Task(JSContext* aCx, const ObjectOrString& aAlgorithm,
-                 mozilla::dom::CryptoKey& aKey, const CryptoOperationData& aData,
+                 CryptoKey& aKey, const CryptoOperationData& aData,
                  bool aEncrypt)
     : mPrivKey(aKey.GetPrivateKey())
     , mPubKey(aKey.GetPublicKey())
     , mEncrypt(aEncrypt)
   {
     Telemetry::Accumulate(Telemetry::WEBCRYPTO_ALG, TA_RSAES_PKCS1);
 
     ATTEMPT_BUFFER_INIT(mData, aData);
@@ -472,21 +472,144 @@ private:
       mResult.SetLength(outLen);
     }
 
     NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_OPERATION_ERR);
     return NS_OK;
   }
 };
 
+class RsaOaepTask : public ReturnArrayBufferViewTask
+{
+public:
+  RsaOaepTask(JSContext* aCx, const ObjectOrString& aAlgorithm,
+              CryptoKey& aKey, const CryptoOperationData& aData,
+              bool aEncrypt)
+    : mPrivKey(aKey.GetPrivateKey())
+    , mPubKey(aKey.GetPublicKey())
+    , mEncrypt(aEncrypt)
+  {
+    Telemetry::Accumulate(Telemetry::WEBCRYPTO_ALG, TA_RSA_OAEP);
+
+    ATTEMPT_BUFFER_INIT(mData, aData);
+
+    if (mEncrypt) {
+      if (!mPubKey) {
+        mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
+        return;
+      }
+      mStrength = SECKEY_PublicKeyStrength(mPubKey);
+    } else {
+      if (!mPrivKey) {
+        mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
+        return;
+      }
+      mStrength = PK11_GetPrivateModulusLen(mPrivKey);
+    }
+
+    RootedDictionary<RsaOaepParams> params(aCx);
+    mEarlyRv = Coerce(aCx, params, aAlgorithm);
+    if (NS_FAILED(mEarlyRv)) {
+      mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
+      return;
+    }
+
+    if (params.mLabel.WasPassed() && !params.mLabel.Value().IsNull()) {
+      ATTEMPT_BUFFER_INIT(mLabel, params.mLabel.Value().Value());
+    }
+    // Otherwise mLabel remains the empty octet string, as intended
+
+    // Look up the MGF based on the KeyAlgorithm.
+    // static_cast is safe because we only get here if the algorithm name
+    // is RSA-OAEP, and that only happens if we've constructed
+    // an RsaHashedKeyAlgorithm.
+    // TODO: Add As* methods to KeyAlgorithm (Bug 1036734)
+    nsRefPtr<RsaHashedKeyAlgorithm> rsaAlg =
+      static_cast<RsaHashedKeyAlgorithm*>(aKey.Algorithm());
+    mHashMechanism = rsaAlg->Hash()->Mechanism();
+
+    switch (mHashMechanism) {
+      case CKM_SHA_1:
+        mMgfMechanism = CKG_MGF1_SHA1; break;
+      case CKM_SHA256:
+        mMgfMechanism = CKG_MGF1_SHA256; break;
+      case CKM_SHA384:
+        mMgfMechanism = CKG_MGF1_SHA384; break;
+      case CKM_SHA512:
+        mMgfMechanism = CKG_MGF1_SHA512; break;
+      default: {
+        mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
+        return;
+      }
+    }
+  }
+
+private:
+  CK_MECHANISM_TYPE mHashMechanism;
+  CK_MECHANISM_TYPE mMgfMechanism;
+  ScopedSECKEYPrivateKey mPrivKey;
+  ScopedSECKEYPublicKey mPubKey;
+  CryptoBuffer mLabel;
+  CryptoBuffer mData;
+  uint32_t mStrength;
+  bool mEncrypt;
+
+  virtual nsresult DoCrypto() MOZ_OVERRIDE
+  {
+    nsresult rv;
+
+    // Ciphertext is an integer mod the modulus, so it will be
+    // no longer than mStrength octets
+    if (!mResult.SetLength(mStrength)) {
+      return NS_ERROR_DOM_UNKNOWN_ERR;
+    }
+
+    CK_RSA_PKCS_OAEP_PARAMS oaepParams;
+    oaepParams.source = CKZ_DATA_SPECIFIED;
+
+    oaepParams.pSourceData = mLabel.Length() ? mLabel.Elements() : nullptr;
+    oaepParams.ulSourceDataLen = mLabel.Length();
+
+    oaepParams.mgf = mMgfMechanism;
+    oaepParams.hashAlg = mHashMechanism;
+
+    SECItem param;
+    param.type = siBuffer;
+    param.data = (unsigned char*) &oaepParams;
+    param.len = sizeof(oaepParams);
+
+    uint32_t outLen;
+    if (mEncrypt) {
+      // PK11_PubEncrypt() checks the plaintext's length and fails if it is too
+      // long to encrypt, i.e. if it is longer than (k - 2hLen - 2) with 'k'
+      // being the length in octets of the RSA modulus n and 'hLen' being the
+      // output length in octets of the chosen hash function.
+      // <https://tools.ietf.org/html/rfc3447#section-7.1>
+      rv = MapSECStatus(PK11_PubEncrypt(
+             mPubKey.get(), CKM_RSA_PKCS_OAEP, &param,
+             mResult.Elements(), &outLen, mResult.Length(),
+             mData.Elements(), mData.Length(), nullptr));
+    } else {
+      rv = MapSECStatus(PK11_PrivDecrypt(
+             mPrivKey.get(), CKM_RSA_PKCS_OAEP, &param,
+             mResult.Elements(), &outLen, mResult.Length(),
+             mData.Elements(), mData.Length()));
+    }
+    mResult.SetLength(outLen);
+
+    NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_OPERATION_ERR);
+    return NS_OK;
+  }
+};
+
 class HmacTask : public WebCryptoTask
 {
 public:
   HmacTask(JSContext* aCx, const ObjectOrString& aAlgorithm,
-           mozilla::dom::CryptoKey& aKey,
+           CryptoKey& aKey,
            const CryptoOperationData& aSignature,
            const CryptoOperationData& aData,
            bool aSign)
     : mMechanism(aKey.Algorithm()->Mechanism())
     , mSymKey(aKey.GetSymKey())
     , mSign(aSign)
   {
     ATTEMPT_BUFFER_INIT(mData, aData);
@@ -579,17 +702,17 @@ private:
     }
   }
 };
 
 class RsassaPkcs1Task : public WebCryptoTask
 {
 public:
   RsassaPkcs1Task(JSContext* aCx, const ObjectOrString& aAlgorithm,
-                  mozilla::dom::CryptoKey& aKey,
+                  CryptoKey& aKey,
                   const CryptoOperationData& aSignature,
                   const CryptoOperationData& aData,
                   bool aSign)
     : mOidTag(SEC_OID_UNKNOWN)
     , mPrivKey(aKey.GetPrivateKey())
     , mPubKey(aKey.GetPublicKey())
     , mSign(aSign)
     , mVerified(false)
@@ -922,17 +1045,18 @@ public:
       mKeyData.Assign(aKeyData.GetAsArrayBuffer());
     } else {
       // TODO This will need to be changed for JWK (Bug 1005220)
       mEarlyRv = NS_ERROR_DOM_DATA_ERR;
       return;
     }
 
     // If this is RSA with a hash, cache the hash name
-    if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
+    if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
+        mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
       RootedDictionary<RsaHashedImportParams> params(aCx);
       mEarlyRv = Coerce(aCx, params, aAlgorithm);
       if (NS_FAILED(mEarlyRv) || !params.mHash.WasPassed()) {
         mEarlyRv = NS_ERROR_DOM_DATA_ERR;
         return;
       }
 
       mEarlyRv = GetAlgorithmName(aCx, params.mHash.Value(), mHashName);
@@ -993,42 +1117,48 @@ private:
 
     return NS_OK;
   }
 
   virtual nsresult AfterCrypto() MOZ_OVERRIDE
   {
     // Construct an appropriate KeyAlgorithm
     nsIGlobalObject* global = mKey->GetParentObject();
-    if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1)) {
+    if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1) ||
+        mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
       if ((mKey->GetKeyType() == CryptoKey::PUBLIC &&
            mKey->HasUsageOtherThan(CryptoKey::ENCRYPT)) ||
           (mKey->GetKeyType() == CryptoKey::PRIVATE &&
            mKey->HasUsageOtherThan(CryptoKey::DECRYPT))) {
         return NS_ERROR_DOM_DATA_ERR;
       }
-
-      mKey->SetAlgorithm(new RsaKeyAlgorithm(global, mAlgName, mModulusLength, mPublicExponent));
     } else if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
       if ((mKey->GetKeyType() == CryptoKey::PUBLIC &&
            mKey->HasUsageOtherThan(CryptoKey::VERIFY)) ||
           (mKey->GetKeyType() == CryptoKey::PRIVATE &&
            mKey->HasUsageOtherThan(CryptoKey::SIGN))) {
         return NS_ERROR_DOM_DATA_ERR;
       }
+    }
 
-      nsRefPtr<RsaHashedKeyAlgorithm> algorithm = new RsaHashedKeyAlgorithm(
-                                                          global,
-                                                          mAlgName,
-                                                          mModulusLength,
-                                                          mPublicExponent,
-                                                          mHashName);
+    // Construct an appropriate KeyAlgorithm
+    if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1)) {
+      mKey->SetAlgorithm(new RsaKeyAlgorithm(global, mAlgName, mModulusLength, mPublicExponent));
+    } else if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
+               mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
+      nsRefPtr<RsaHashedKeyAlgorithm> algorithm =
+        new RsaHashedKeyAlgorithm(global, mAlgName,
+                                  mModulusLength, mPublicExponent, mHashName);
       if (algorithm->Mechanism() == UNKNOWN_CK_MECHANISM) {
         return NS_ERROR_DOM_SYNTAX_ERR;
       }
+
+      if (algorithm->Hash()->Mechanism() == UNKNOWN_CK_MECHANISM) {
+        return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
+      }
       mKey->SetAlgorithm(algorithm);
     }
 
     return NS_OK;
   }
 };
 
 
@@ -1271,17 +1401,18 @@ public:
     if (NS_FAILED(mEarlyRv)) {
       mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
       return;
     }
 
     // Construct an appropriate KeyAlorithm
     KeyAlgorithm* algorithm;
     uint32_t privateAllowedUsages = 0, publicAllowedUsages = 0;
-    if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
+    if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
+        algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
       RootedDictionary<RsaHashedKeyGenParams> params(aCx);
       mEarlyRv = Coerce(aCx, params, aAlgorithm);
       if (NS_FAILED(mEarlyRv) || !params.mModulusLength.WasPassed() ||
           !params.mPublicExponent.WasPassed() ||
           !params.mHash.WasPassed()) {
         mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
         return;
       }
@@ -1306,19 +1437,16 @@ public:
 
       // Set up params struct
       mRsaParams.keySizeInBits = modulusLength;
       bool converted = publicExponent.GetBigIntValue(mRsaParams.pe);
       if (!converted) {
         mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
         return;
       }
-
-      privateAllowedUsages = CryptoKey::SIGN;
-      publicAllowedUsages = CryptoKey::VERIFY;
     } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1)) {
       RootedDictionary<RsaKeyGenParams> params(aCx);
       mEarlyRv = Coerce(aCx, params, aAlgorithm);
       if (NS_FAILED(mEarlyRv) || !params.mModulusLength.WasPassed() ||
           !params.mPublicExponent.WasPassed()) {
         mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
         return;
       }
@@ -1337,24 +1465,31 @@ public:
 
       // Set up params struct
       mRsaParams.keySizeInBits = modulusLength;
       bool converted = publicExponent.GetBigIntValue(mRsaParams.pe);
       if (!converted) {
         mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
         return;
       }
-
-      privateAllowedUsages = CryptoKey::DECRYPT | CryptoKey::UNWRAPKEY;
-      publicAllowedUsages = CryptoKey::ENCRYPT | CryptoKey::WRAPKEY;
     } else {
       mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
       return;
     }
 
+    // Set key usages.
+    if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
+      privateAllowedUsages = CryptoKey::SIGN;
+      publicAllowedUsages = CryptoKey::VERIFY;
+    } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1) ||
+               algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
+      privateAllowedUsages = CryptoKey::DECRYPT | CryptoKey::UNWRAPKEY;
+      publicAllowedUsages = CryptoKey::ENCRYPT | CryptoKey::WRAPKEY;
+    }
+
     mKeyPair->PrivateKey()->SetExtractable(aExtractable);
     mKeyPair->PrivateKey()->SetType(CryptoKey::PRIVATE);
 
     mKeyPair->PublicKey()->SetExtractable(true);
     mKeyPair->PublicKey()->SetType(CryptoKey::PUBLIC);
 
     mKeyPair->PrivateKey()->ClearUsages();
     mKeyPair->PublicKey()->ClearUsages();
@@ -1448,16 +1583,18 @@ WebCryptoTask::EncryptDecryptTask(JSCont
   }
 
   if (algName.EqualsLiteral(WEBCRYPTO_ALG_AES_CBC) ||
       algName.EqualsLiteral(WEBCRYPTO_ALG_AES_CTR) ||
       algName.EqualsLiteral(WEBCRYPTO_ALG_AES_GCM)) {
     return new AesTask(aCx, aAlgorithm, aKey, aData, aEncrypt);
   } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1)) {
     return new RsaesPkcs1Task(aCx, aAlgorithm, aKey, aData, aEncrypt);
+  } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
+    return new RsaOaepTask(aCx, aAlgorithm, aKey, aData, aEncrypt);
   }
 
   return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
 }
 
 WebCryptoTask*
 WebCryptoTask::SignVerifyTask(JSContext* aCx,
                               const ObjectOrString& aAlgorithm,
@@ -1519,17 +1656,18 @@ WebCryptoTask::ImportKeyTask(JSContext* 
 
   if (algName.EqualsLiteral(WEBCRYPTO_ALG_AES_CBC) ||
       algName.EqualsLiteral(WEBCRYPTO_ALG_AES_CTR) ||
       algName.EqualsLiteral(WEBCRYPTO_ALG_AES_GCM) ||
       algName.EqualsLiteral(WEBCRYPTO_ALG_HMAC)) {
     return new ImportSymmetricKeyTask(aCx, aFormat, aKeyData, aAlgorithm,
                                       aExtractable, aKeyUsages);
   } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1) ||
-             algName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
+             algName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
+             algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
     return new ImportRsaKeyTask(aCx, aFormat, aKeyData, aAlgorithm,
                                 aExtractable, aKeyUsages);
   } else {
     return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
   }
 }
 
 WebCryptoTask*
@@ -1561,17 +1699,18 @@ WebCryptoTask::GenerateKeyTask(JSContext
   }
 
   if (algName.EqualsASCII(WEBCRYPTO_ALG_AES_CBC) ||
       algName.EqualsASCII(WEBCRYPTO_ALG_AES_CTR) ||
       algName.EqualsASCII(WEBCRYPTO_ALG_AES_GCM) ||
       algName.EqualsASCII(WEBCRYPTO_ALG_HMAC)) {
     return new GenerateSymmetricKeyTask(aCx, aAlgorithm, aExtractable, aKeyUsages);
   } else if (algName.EqualsASCII(WEBCRYPTO_ALG_RSAES_PKCS1) ||
-             algName.EqualsASCII(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
+             algName.EqualsASCII(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
+             algName.EqualsASCII(WEBCRYPTO_ALG_RSA_OAEP)) {
     return new GenerateAsymmetricKeyTask(aCx, aAlgorithm, aExtractable, aKeyUsages);
   } else {
     return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
   }
 }
 
 WebCryptoTask*
 WebCryptoTask::DeriveKeyTask(JSContext* aCx,
--- a/dom/webidl/SubtleCrypto.webidl
+++ b/dom/webidl/SubtleCrypto.webidl
@@ -84,16 +84,20 @@ dictionary RsaKeyGenParams : Algorithm {
   [EnforceRange] unsigned long modulusLength;
   BigInteger publicExponent;
 };
 
 dictionary RsaHashedKeyGenParams : RsaKeyGenParams {
   AlgorithmIdentifier hash;
 };
 
+dictionary RsaOaepParams : Algorithm {
+  CryptoOperationData? label;
+};
+
 dictionary DhKeyGenParams : Algorithm {
   BigInteger prime;
   BigInteger generator;
 };
 
 typedef DOMString NamedCurve;
 dictionary EcKeyGenParams : Algorithm {
   NamedCurve namedCurve;
--- a/security/build/nss.def
+++ b/security/build/nss.def
@@ -390,19 +390,21 @@ PK11_MechanismToAlgtag
 PK11_MergeTokens
 PK11_NeedLogin
 PK11_NeedUserInit
 PK11_ParamFromIV
 PK11_PBEKeyGen
 PK11_PQG_DestroyParams
 PK11_PQG_DestroyVerify
 PK11_PQG_ParamGen
+PK11_PrivDecrypt
 PK11_PrivDecryptPKCS1
 PK11_ProtectedAuthenticationPath
 PK11_PubDeriveWithKDF
+PK11_PubEncrypt
 PK11_PubEncryptPKCS1
 PK11_PubUnwrapSymKey
 PK11_PubWrapSymKey
 PK11_RandomUpdate
 PK11_ReadRawAttribute
 PK11_ReferenceSlot
 PK11_ResetToken
 PK11SDR_Decrypt