Bug 1034856 - Implement generateKey() for DH r=rbarnes

This commit is contained in:
Tim Taubert 2014-07-20 06:38:44 +02:00
parent c8d7544c93
commit 888df14c06
6 changed files with 159 additions and 11 deletions

View File

@ -161,6 +161,20 @@ CryptoBuffer::ToSECItem() const
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*
CryptoBuffer::ToUint8Array(JSContext* aCx) const
{

View File

@ -40,6 +40,7 @@ public:
nsresult FromJwkBase64(const nsString& aBase64);
nsresult ToJwkBase64(nsString& aBase64);
SECItem* ToSECItem() const;
bool ToSECItem(PLArenaPool* aArena, SECItem* aItem) const;
JSObject* ToUint8Array(JSContext* aCx) const;
bool GetBigIntValue(unsigned long& aRetVal);

View File

@ -2008,6 +2008,12 @@ public:
return;
}
mArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (!mArena) {
mEarlyRv = NS_ERROR_DOM_UNKNOWN_ERR;
return;
}
// Create an empty key and set easy attributes
mKeyPair.mPrivateKey = new CryptoKey(global);
mKeyPair.mPublicKey = new CryptoKey(global);
@ -2078,6 +2084,31 @@ public:
mKeyPair.mPublicKey.get()->Algorithm().MakeEc(algName, mNamedCurve);
mKeyPair.mPrivateKey.get()->Algorithm().MakeEc(algName, mNamedCurve);
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 {
mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
return;
@ -2091,7 +2122,8 @@ public:
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
privateAllowedUsages = CryptoKey::DECRYPT | CryptoKey::UNWRAPKEY;
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;
publicAllowedUsages = 0;
}
@ -2127,9 +2159,11 @@ public:
}
private:
ScopedPLArenaPool mArena;
CryptoKeyPair mKeyPair;
CK_MECHANISM_TYPE mMechanism;
PK11RSAGenParams mRsaParams;
SECKEYDHParams mDhParams;
ScopedSECKEYPublicKey mPublicKey;
ScopedSECKEYPrivateKey mPrivateKey;
nsString mNamedCurve;
@ -2146,19 +2180,15 @@ private:
MOZ_ASSERT(slot.get());
void* param;
ScopedPLArenaPool arena;
switch (mMechanism) {
case CKM_RSA_PKCS_KEY_PAIR_GEN:
param = &mRsaParams;
break;
case CKM_DH_PKCS_KEY_PAIR_GEN:
param = &mDhParams;
break;
case CKM_EC_KEY_PAIR_GEN: {
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (!arena) {
return NS_ERROR_DOM_UNKNOWN_ERR;
}
param = CreateECParamsForCurve(mNamedCurve, arena.get());
param = CreateECParamsForCurve(mNamedCurve, mArena);
if (!param) {
return NS_ERROR_DOM_UNKNOWN_ERR;
}
@ -2768,7 +2798,8 @@ WebCryptoTask::CreateGenerateKeyTask(JSContext* aCx,
} else if (algName.EqualsASCII(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
algName.EqualsASCII(WEBCRYPTO_ALG_RSA_OAEP) ||
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);
} else {
return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);

View File

@ -8,6 +8,7 @@ support-files =
util.js
[test_WebCrypto.html]
[test_WebCrypto_DH.html]
[test_WebCrypto_ECDH.html]
[test_WebCrypto_JWK.html]
[test_WebCrypto_PBKDF2.html]

View File

@ -657,5 +657,14 @@ tv = {
"y": "AUNouOdGgHsraPNhXNeNdhpGTd15GPyN9R0iWWL98ePc" +
"JD4mUQD/DsEzNZ4zLkTdSa/Y5fOP6GEzVzQy0zwC+goD"
}
}
},
// RFC 2409 <http://tools.ietf.org/html/rfc2409#section-6.1>
dh: {
prime: util.hex2abv(
"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74" +
"020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f1437" +
"4fe1356d6d51c245e485b576625e7ec6f44c42e9a63a3620ffffffffffffffff"
)
},
}

View 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>