Bug 1026398 - Add support for RSA-OAEP to WebCrypto API r=rbarnes,bz,dkeeler

* * *
Bug 1026398 - Add RSA-OAEP tests r=rbarnes
This commit is contained in:
Tim Taubert 2014-07-14 18:33:12 -07:00
parent c15523f3cf
commit 04422d6b32
7 changed files with 343 additions and 27 deletions

View File

@ -24,6 +24,7 @@
#define WEBCRYPTO_ALG_PBKDF2 "PBKDF2"
#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"
@ -146,6 +147,8 @@ MapAlgorithmNameToMechanism(const nsString& aName)
mechanism = CKM_RSA_PKCS;
} else if (aName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
mechanism = CKM_RSA_PKCS;
} else if (aName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
mechanism = CKM_RSA_PKCS_OAEP;
}
return mechanism;

View File

@ -303,7 +303,7 @@ 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)
@ -480,7 +480,7 @@ 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())
@ -549,11 +549,134 @@ private:
}
};
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)
@ -656,7 +779,7 @@ 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)
@ -1017,7 +1140,8 @@ public:
}
// 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()) {
@ -1088,15 +1212,14 @@ private:
{
// 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)) ||
@ -1104,16 +1227,23 @@ 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);
}
@ -1345,7 +1475,8 @@ public:
// 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() ||
@ -1380,9 +1511,6 @@ public:
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);
@ -1411,14 +1539,21 @@ public:
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);
@ -1676,6 +1811,8 @@ WebCryptoTask::EncryptDecryptTask(JSContext* aCx,
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);
@ -1748,7 +1885,8 @@ WebCryptoTask::ImportKeyTask(JSContext* aCx,
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 {
@ -1790,7 +1928,8 @@ WebCryptoTask::GenerateKeyTask(JSContext* aCx,
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);

View File

@ -1,6 +1,6 @@
[DEFAULT]
# Bug 1010743 - Re-enable WebCrypto tests on b2g-desktop
skip-if = (buildapp == 'b2g' && toolkit != 'gonk')
# Bug 1010743 - Re-enable WebCrypto tests on b2g
skip-if = (buildapp == 'b2g')
support-files =
test-array.js
test-vectors.js

View File

@ -311,6 +311,50 @@ tv = {
),
},
// RSA test vectors, oaep-vect.txt, Example 1.1: A 1024-bit RSA Key Pair
// <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip>
rsaoaep: {
pkcs8: util.hex2abv(
"30820276020100300d06092a864886f70d0101010500048202603082025c0201" +
"0002818100a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae" +
"4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630" +
"f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fa" +
"b9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de" +
"88d39f16fb020301000102818053339cfdb79fc8466a655c7316aca85c55fd8f" +
"6dd898fdaf119517ef4f52e8fd8e258df93fee180fa0e4ab29693cd83b152a55" +
"3d4ac4d1812b8b9fa5af0e7f55fe7304df41570926f3311f15c4d65a732c4831" +
"16ee3d3d2d0af3549ad9bf7cbfb78ad884f84d5beb04724dc7369b31def37d0c" +
"f539e9cfcdd3de653729ead5d1024100d32737e7267ffe1341b2d5c0d150a81b" +
"586fb3132bed2f8d5262864a9cb9f30af38be448598d413a172efb802c21acf1" +
"c11c520c2f26a471dcad212eac7ca39d024100cc8853d1d54da630fac004f471" +
"f281c7b8982d8224a490edbeb33d3e3d5cc93c4765703d1dd791642f1f116a0d" +
"d852be2419b2af72bfe9a030e860b0288b5d7702400e12bf1718e9cef5599ba1" +
"c3882fe8046a90874eefce8f2ccc20e4f2741fb0a33a3848aec9c9305fbecbd2" +
"d76819967d4671acc6431e4037968db37878e695c102410095297b0f95a2fa67" +
"d00707d609dfd4fc05c89dafc2ef6d6ea55bec771ea333734d9251e79082ecda" +
"866efef13c459e1a631386b7e354c899f5f112ca85d7158302404f456c502493" +
"bdc0ed2ab756a3a6ed4d67352a697d4216e93212b127a63d5411ce6fa98d5dbe" +
"fd73263e3728142743818166ed7dd63687dd2a8ca1d2f4fbd8e1"
),
spki: util.hex2abv(
"30819f300d06092a864886f70d010101050003818d0030818902818100a8b3b2" +
"84af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0" +
"b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae8" +
"33c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef739" +
"2dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb020301" +
"0001"
),
data: util.hex2abv(
"6628194e12073db03ba94cda9ef9532397d50dba79b987004afefe34"
),
result: util.hex2abv(
"354fe67b4a126d5d35fe36c777791a3f7ba13def484e2d3908aff722fad468fb" +
"21696de95d0be911c2d3174f8afcc201035f7b6d8e69402de5451618c21a535f" +
"a9d7bfc5b8dd9fc243f8cf927db31322d6e881eaa91a996170e657a05a266426" +
"d98c88003f8477c1227094a0d9fa1e8c4024309ce1ecccb5210035d47ac72e8a"
),
},
// RFC 6070 <http://tools.ietf.org/html/rfc6070>
pbkdf2_sha1: {
password: new TextEncoder("utf-8").encode("passwordPASSWORDpassword"),

View File

@ -154,7 +154,7 @@ TestArray.addTest(
"Import / export round-trip with 'pkcs8'",
function() {
var that = this;
var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA1" };
var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-1" };
function doExport(x) {
if (!hasKeyFields(x)) {
@ -186,7 +186,7 @@ TestArray.addTest(
"Import failure with format 'pkcs8'",
function() {
var that = this;
var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA1" };
var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-1" };
crypto.subtle.importKey("pkcs8", tv.negative_pkcs8, alg, true, ["encrypt"])
.then(error(that), complete(that));
@ -1150,3 +1150,127 @@ TestArray.addTest(
.then( memcmp_complete(that, tv.pbkdf2_sha256.derived), fail );
}
);*/
// -----------------------------------------------------------------------------
TestArray.addTest(
"RSA-OAEP encrypt/decrypt round-trip",
function () {
var that = this;
var privKey, pubKey;
var alg = {name: "RSA-OAEP", hash: "SHA-1"};
var privKey, pubKey;
function setPriv(x) { privKey = x; }
function setPub(x) { pubKey = x; }
function doEncrypt() {
return crypto.subtle.encrypt(alg, pubKey, tv.rsaoaep.data);
}
function doDecrypt(x) {
return crypto.subtle.decrypt(alg, privKey, x);
}
Promise.all([
crypto.subtle.importKey("pkcs8", tv.rsaoaep.pkcs8, alg, false, ['decrypt'])
.then(setPriv, error(that)),
crypto.subtle.importKey("spki", tv.rsaoaep.spki, alg, false, ['encrypt'])
.then(setPub, error(that))
]).then(doEncrypt, error(that))
.then(doDecrypt, error(that))
.then(
memcmp_complete(that, tv.rsaoaep.data),
error(that)
);
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"RSA-OAEP key generation and encrypt/decrypt round-trip (SHA-256)",
function () {
var that = this;
var alg = {
name: "RSA-OAEP",
hash: "SHA-256",
modulusLength: 2048,
publicExponent: new Uint8Array([0x01, 0x00, 0x01])
};
var privKey, pubKey, data = crypto.getRandomValues(new Uint8Array(128));
function setKey(x) { pubKey = x.publicKey; privKey = x.privateKey; }
function doEncrypt() {
return crypto.subtle.encrypt(alg, pubKey, data);
}
function doDecrypt(x) {
return crypto.subtle.decrypt(alg, privKey, x);
}
crypto.subtle.generateKey(alg, false, ['encrypt', 'decrypt'])
.then(setKey, error(that))
.then(doEncrypt, error(that))
.then(doDecrypt, error(that))
.then(
memcmp_complete(that, data),
error(that)
);
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"RSA-OAEP decryption known answer",
function () {
var that = this;
var alg = {name: "RSA-OAEP", hash: "SHA-1"};
function doDecrypt(x) {
return crypto.subtle.decrypt(alg, x, tv.rsaoaep.result);
}
function fail() { error(that); }
crypto.subtle.importKey("pkcs8", tv.rsaoaep.pkcs8, alg, false, ['decrypt'])
.then( doDecrypt, fail )
.then( memcmp_complete(that, tv.rsaoaep.data), fail );
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"RSA-OAEP input data length checks (2048-bit key)",
function () {
var that = this;
var privKey, pubKey;
var alg = {
name: "RSA-OAEP",
hash: "SHA-1",
modulusLength: 2048,
publicExponent: new Uint8Array([0x01, 0x00, 0x01])
};
var privKey, pubKey;
function setKey(x) { pubKey = x.publicKey; privKey = x.privateKey; }
function doEncrypt(n) {
return function () {
return crypto.subtle.encrypt(alg, pubKey, new Uint8Array(n));
}
}
crypto.subtle.generateKey(alg, false, ['encrypt'])
.then(setKey, error(that))
.then(doEncrypt(214), error(that))
.then(doEncrypt(215), error(that))
.then(error(that), complete(that));
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"RSA-OAEP key import with invalid hash",
function () {
var that = this;
var alg = {name: "RSA-OAEP", hash: "SHA-123"};
crypto.subtle.importKey("pkcs8", tv.rsaoaep.pkcs8, alg, false, ['decrypt'])
.then(error(that), complete(that));
}
);

View File

@ -95,6 +95,10 @@ dictionary RsaHashedKeyGenParams : RsaKeyGenParams {
AlgorithmIdentifier hash;
};
dictionary RsaOaepParams : Algorithm {
CryptoOperationData? label;
};
dictionary DhKeyGenParams : Algorithm {
BigInteger prime;
BigInteger generator;

View File

@ -395,9 +395,11 @@ 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