Bug 1034856 - Implement generateKey() for DH r=rbarnes
This commit is contained in:
@@ -161,6 +161,20 @@ CryptoBuffer::ToSECItem() const
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CryptoBuffer::ToSECItem(PLArenaPool *aArena, SECItem* aItem) const
|
||||||
|
{
|
||||||
|
aItem->type = siBuffer;
|
||||||
|
aItem->data = nullptr;
|
||||||
|
|
||||||
|
if (!::SECITEM_AllocItem(aArena, aItem, Length())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(aItem->data, Elements(), Length());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
JSObject*
|
JSObject*
|
||||||
CryptoBuffer::ToUint8Array(JSContext* aCx) const
|
CryptoBuffer::ToUint8Array(JSContext* aCx) const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ public:
|
|||||||
nsresult FromJwkBase64(const nsString& aBase64);
|
nsresult FromJwkBase64(const nsString& aBase64);
|
||||||
nsresult ToJwkBase64(nsString& aBase64);
|
nsresult ToJwkBase64(nsString& aBase64);
|
||||||
SECItem* ToSECItem() const;
|
SECItem* ToSECItem() const;
|
||||||
|
bool ToSECItem(PLArenaPool* aArena, SECItem* aItem) const;
|
||||||
JSObject* ToUint8Array(JSContext* aCx) const;
|
JSObject* ToUint8Array(JSContext* aCx) const;
|
||||||
|
|
||||||
bool GetBigIntValue(unsigned long& aRetVal);
|
bool GetBigIntValue(unsigned long& aRetVal);
|
||||||
|
|||||||
@@ -2008,6 +2008,12 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
||||||
|
if (!mArena) {
|
||||||
|
mEarlyRv = NS_ERROR_DOM_UNKNOWN_ERR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Create an empty key and set easy attributes
|
// Create an empty key and set easy attributes
|
||||||
mKeyPair.mPrivateKey = new CryptoKey(global);
|
mKeyPair.mPrivateKey = new CryptoKey(global);
|
||||||
mKeyPair.mPublicKey = new CryptoKey(global);
|
mKeyPair.mPublicKey = new CryptoKey(global);
|
||||||
@@ -2078,6 +2084,31 @@ public:
|
|||||||
mKeyPair.mPublicKey.get()->Algorithm().MakeEc(algName, mNamedCurve);
|
mKeyPair.mPublicKey.get()->Algorithm().MakeEc(algName, mNamedCurve);
|
||||||
mKeyPair.mPrivateKey.get()->Algorithm().MakeEc(algName, mNamedCurve);
|
mKeyPair.mPrivateKey.get()->Algorithm().MakeEc(algName, mNamedCurve);
|
||||||
mMechanism = CKM_EC_KEY_PAIR_GEN;
|
mMechanism = CKM_EC_KEY_PAIR_GEN;
|
||||||
|
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_DH)) {
|
||||||
|
RootedDictionary<DhKeyGenParams> params(aCx);
|
||||||
|
mEarlyRv = Coerce(aCx, params, aAlgorithm);
|
||||||
|
if (NS_FAILED(mEarlyRv)) {
|
||||||
|
mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CryptoBuffer prime;
|
||||||
|
ATTEMPT_BUFFER_INIT(prime, params.mPrime);
|
||||||
|
|
||||||
|
CryptoBuffer generator;
|
||||||
|
ATTEMPT_BUFFER_INIT(generator, params.mGenerator);
|
||||||
|
|
||||||
|
// Set up params.
|
||||||
|
if (!prime.ToSECItem(mArena, &mDhParams.prime) ||
|
||||||
|
!generator.ToSECItem(mArena, &mDhParams.base)) {
|
||||||
|
mEarlyRv = NS_ERROR_DOM_UNKNOWN_ERR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create algorithm.
|
||||||
|
mKeyPair.mPublicKey.get()->Algorithm().MakeDh(algName, prime, generator);
|
||||||
|
mKeyPair.mPrivateKey.get()->Algorithm().MakeDh(algName, prime, generator);
|
||||||
|
mMechanism = CKM_DH_PKCS_KEY_PAIR_GEN;
|
||||||
} else {
|
} else {
|
||||||
mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
||||||
return;
|
return;
|
||||||
@@ -2091,7 +2122,8 @@ public:
|
|||||||
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
|
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
|
||||||
privateAllowedUsages = CryptoKey::DECRYPT | CryptoKey::UNWRAPKEY;
|
privateAllowedUsages = CryptoKey::DECRYPT | CryptoKey::UNWRAPKEY;
|
||||||
publicAllowedUsages = CryptoKey::ENCRYPT | CryptoKey::WRAPKEY;
|
publicAllowedUsages = CryptoKey::ENCRYPT | CryptoKey::WRAPKEY;
|
||||||
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_ECDH)) {
|
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_ECDH) ||
|
||||||
|
algName.EqualsLiteral(WEBCRYPTO_ALG_DH)) {
|
||||||
privateAllowedUsages = CryptoKey::DERIVEKEY | CryptoKey::DERIVEBITS;
|
privateAllowedUsages = CryptoKey::DERIVEKEY | CryptoKey::DERIVEBITS;
|
||||||
publicAllowedUsages = 0;
|
publicAllowedUsages = 0;
|
||||||
}
|
}
|
||||||
@@ -2127,9 +2159,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
ScopedPLArenaPool mArena;
|
||||||
CryptoKeyPair mKeyPair;
|
CryptoKeyPair mKeyPair;
|
||||||
CK_MECHANISM_TYPE mMechanism;
|
CK_MECHANISM_TYPE mMechanism;
|
||||||
PK11RSAGenParams mRsaParams;
|
PK11RSAGenParams mRsaParams;
|
||||||
|
SECKEYDHParams mDhParams;
|
||||||
ScopedSECKEYPublicKey mPublicKey;
|
ScopedSECKEYPublicKey mPublicKey;
|
||||||
ScopedSECKEYPrivateKey mPrivateKey;
|
ScopedSECKEYPrivateKey mPrivateKey;
|
||||||
nsString mNamedCurve;
|
nsString mNamedCurve;
|
||||||
@@ -2146,19 +2180,15 @@ private:
|
|||||||
MOZ_ASSERT(slot.get());
|
MOZ_ASSERT(slot.get());
|
||||||
|
|
||||||
void* param;
|
void* param;
|
||||||
ScopedPLArenaPool arena;
|
|
||||||
|
|
||||||
switch (mMechanism) {
|
switch (mMechanism) {
|
||||||
case CKM_RSA_PKCS_KEY_PAIR_GEN:
|
case CKM_RSA_PKCS_KEY_PAIR_GEN:
|
||||||
param = &mRsaParams;
|
param = &mRsaParams;
|
||||||
break;
|
break;
|
||||||
|
case CKM_DH_PKCS_KEY_PAIR_GEN:
|
||||||
|
param = &mDhParams;
|
||||||
|
break;
|
||||||
case CKM_EC_KEY_PAIR_GEN: {
|
case CKM_EC_KEY_PAIR_GEN: {
|
||||||
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
param = CreateECParamsForCurve(mNamedCurve, mArena);
|
||||||
if (!arena) {
|
|
||||||
return NS_ERROR_DOM_UNKNOWN_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
param = CreateECParamsForCurve(mNamedCurve, arena.get());
|
|
||||||
if (!param) {
|
if (!param) {
|
||||||
return NS_ERROR_DOM_UNKNOWN_ERR;
|
return NS_ERROR_DOM_UNKNOWN_ERR;
|
||||||
}
|
}
|
||||||
@@ -2768,7 +2798,8 @@ WebCryptoTask::CreateGenerateKeyTask(JSContext* aCx,
|
|||||||
} else if (algName.EqualsASCII(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
|
} else if (algName.EqualsASCII(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
|
||||||
algName.EqualsASCII(WEBCRYPTO_ALG_RSA_OAEP) ||
|
algName.EqualsASCII(WEBCRYPTO_ALG_RSA_OAEP) ||
|
||||||
algName.EqualsASCII(WEBCRYPTO_ALG_ECDH) ||
|
algName.EqualsASCII(WEBCRYPTO_ALG_ECDH) ||
|
||||||
algName.EqualsASCII(WEBCRYPTO_ALG_ECDSA)) {
|
algName.EqualsASCII(WEBCRYPTO_ALG_ECDSA) ||
|
||||||
|
algName.EqualsASCII(WEBCRYPTO_ALG_DH)) {
|
||||||
return new GenerateAsymmetricKeyTask(aCx, aAlgorithm, aExtractable, aKeyUsages);
|
return new GenerateAsymmetricKeyTask(aCx, aAlgorithm, aExtractable, aKeyUsages);
|
||||||
} else {
|
} else {
|
||||||
return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ support-files =
|
|||||||
util.js
|
util.js
|
||||||
|
|
||||||
[test_WebCrypto.html]
|
[test_WebCrypto.html]
|
||||||
|
[test_WebCrypto_DH.html]
|
||||||
[test_WebCrypto_ECDH.html]
|
[test_WebCrypto_ECDH.html]
|
||||||
[test_WebCrypto_JWK.html]
|
[test_WebCrypto_JWK.html]
|
||||||
[test_WebCrypto_PBKDF2.html]
|
[test_WebCrypto_PBKDF2.html]
|
||||||
|
|||||||
@@ -657,5 +657,14 @@ tv = {
|
|||||||
"y": "AUNouOdGgHsraPNhXNeNdhpGTd15GPyN9R0iWWL98ePc" +
|
"y": "AUNouOdGgHsraPNhXNeNdhpGTd15GPyN9R0iWWL98ePc" +
|
||||||
"JD4mUQD/DsEzNZ4zLkTdSa/Y5fOP6GEzVzQy0zwC+goD"
|
"JD4mUQD/DsEzNZ4zLkTdSa/Y5fOP6GEzVzQy0zwC+goD"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
|
// RFC 2409 <http://tools.ietf.org/html/rfc2409#section-6.1>
|
||||||
|
dh: {
|
||||||
|
prime: util.hex2abv(
|
||||||
|
"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74" +
|
||||||
|
"020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f1437" +
|
||||||
|
"4fe1356d6d51c245e485b576625e7ec6f44c42e9a63a3620ffffffffffffffff"
|
||||||
|
)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
92
dom/crypto/test/test_WebCrypto_DH.html
Normal file
92
dom/crypto/test/test_WebCrypto_DH.html
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>WebCrypto Test Suite</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
||||||
|
<link rel="stylesheet" href="./test_WebCrypto.css"/>
|
||||||
|
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
|
||||||
|
<!-- Utilities for manipulating ABVs -->
|
||||||
|
<script src="util.js"></script>
|
||||||
|
|
||||||
|
<!-- A simple wrapper around IndexedDB -->
|
||||||
|
<script src="simpledb.js"></script>
|
||||||
|
|
||||||
|
<!-- Test vectors drawn from the literature -->
|
||||||
|
<script src="./test-vectors.js"></script>
|
||||||
|
|
||||||
|
<!-- General testing framework -->
|
||||||
|
<script src="./test-array.js"></script>
|
||||||
|
|
||||||
|
<script>/*<![CDATA[*/
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
TestArray.addTest(
|
||||||
|
"Generate a DH key",
|
||||||
|
function() {
|
||||||
|
var that = this;
|
||||||
|
var alg = {
|
||||||
|
name: "DH",
|
||||||
|
prime: tv.dh.prime,
|
||||||
|
generator: new Uint8Array([0x02])
|
||||||
|
};
|
||||||
|
crypto.subtle.generateKey(alg, false, ["deriveKey", "deriveBits"]).then(
|
||||||
|
complete(that, function(x) {
|
||||||
|
return exists(x.publicKey) &&
|
||||||
|
(x.publicKey.algorithm.name == alg.name) &&
|
||||||
|
util.memcmp(x.publicKey.algorithm.prime, alg.prime) &&
|
||||||
|
util.memcmp(x.publicKey.algorithm.generator, alg.generator) &&
|
||||||
|
(x.publicKey.type == "public") &&
|
||||||
|
x.publicKey.extractable &&
|
||||||
|
(x.publicKey.usages.length == 0) &&
|
||||||
|
exists(x.privateKey) &&
|
||||||
|
(x.privateKey.algorithm.name == alg.name) &&
|
||||||
|
util.memcmp(x.privateKey.algorithm.prime, alg.prime) &&
|
||||||
|
util.memcmp(x.privateKey.algorithm.generator, alg.generator) &&
|
||||||
|
(x.privateKey.type == "private") &&
|
||||||
|
!x.privateKey.extractable &&
|
||||||
|
(x.privateKey.usages.length == 2) &&
|
||||||
|
(x.privateKey.usages[0] == "deriveKey") &&
|
||||||
|
(x.privateKey.usages[1] == "deriveBits");
|
||||||
|
}),
|
||||||
|
error(that)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
/*]]>*/</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="content">
|
||||||
|
<div id="head">
|
||||||
|
<b>Web</b>Crypto<br>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="start" onclick="start();">RUN ALL</div>
|
||||||
|
|
||||||
|
<div id="resultDiv" class="content">
|
||||||
|
Summary:
|
||||||
|
<span class="pass"><span id="passN">0</span> passed, </span>
|
||||||
|
<span class="fail"><span id="failN">0</span> failed, </span>
|
||||||
|
<span class="pending"><span id="pendingN">0</span> pending.</span>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<table id="results">
|
||||||
|
<tr>
|
||||||
|
<th>Test</th>
|
||||||
|
<th>Result</th>
|
||||||
|
<th>Time</th>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="foot"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user