Bug 1048133 - Check key algorithms before using them for encryption/signatures r=rbarnes a=abillings

This commit is contained in:
Tim Taubert 2014-08-04 14:31:17 +02:00
parent a534663c41
commit 66e3ad7f14
2 changed files with 69 additions and 8 deletions

View File

@ -96,6 +96,17 @@ enum TelemetryAlgorithm {
return NS_ERROR_DOM_UNKNOWN_ERR; \
}
// Safety check for algorithms that use keys, suitable for constructors
#define CHECK_KEY_ALGORITHM(keyAlg, algName) \
{ \
nsString keyAlgName; \
keyAlg->GetName(keyAlgName); \
if (!keyAlgName.EqualsLiteral(algName)) { \
mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR; \
return; \
} \
}
class ClearException
{
public:
@ -447,6 +458,8 @@ public:
// Cache parameters depending on the specific algorithm
TelemetryAlgorithm telemetryAlg;
if (algName.EqualsLiteral(WEBCRYPTO_ALG_AES_CBC)) {
CHECK_KEY_ALGORITHM(aKey.Algorithm(), WEBCRYPTO_ALG_AES_CBC);
mMechanism = CKM_AES_CBC_PAD;
telemetryAlg = TA_AES_CBC;
AesCbcParams params;
@ -462,6 +475,8 @@ public:
return;
}
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_AES_CTR)) {
CHECK_KEY_ALGORITHM(aKey.Algorithm(), WEBCRYPTO_ALG_AES_CTR);
mMechanism = CKM_AES_CTR;
telemetryAlg = TA_AES_CTR;
AesCtrParams params;
@ -480,6 +495,8 @@ public:
mCounterLength = params.mLength.Value();
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_AES_GCM)) {
CHECK_KEY_ALGORITHM(aKey.Algorithm(), WEBCRYPTO_ALG_AES_GCM);
mMechanism = CKM_AES_GCM;
telemetryAlg = TA_AES_GCM;
AesGcmParams params;
@ -627,6 +644,8 @@ public:
void Init(JSContext* aCx, const ObjectOrString& aAlgorithm,
CryptoKey& aKey, bool aEncrypt)
{
CHECK_KEY_ALGORITHM(aKey.Algorithm(), WEBCRYPTO_ALG_AES_KW);
nsString algName;
mEarlyRv = GetAlgorithmName(aCx, aAlgorithm, algName);
if (NS_FAILED(mEarlyRv)) {
@ -754,6 +773,8 @@ public:
Telemetry::Accumulate(Telemetry::WEBCRYPTO_ALG, TA_RSAES_PKCS1);
CHECK_KEY_ALGORITHM(aKey.Algorithm(), WEBCRYPTO_ALG_RSAES_PKCS1);
if (mEncrypt) {
if (!mPubKey) {
mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
@ -849,6 +870,8 @@ public:
{
Telemetry::Accumulate(Telemetry::WEBCRYPTO_ALG, TA_RSA_OAEP);
CHECK_KEY_ALGORITHM(aKey.Algorithm(), WEBCRYPTO_ALG_RSA_OAEP);
if (mEncrypt) {
if (!mPubKey) {
mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
@ -977,6 +1000,8 @@ public:
, mSymKey(aKey.GetSymKey())
, mSign(aSign)
{
CHECK_KEY_ALGORITHM(aKey.Algorithm(), WEBCRYPTO_ALG_HMAC);
ATTEMPT_BUFFER_INIT(mData, aData);
if (!aSign) {
ATTEMPT_BUFFER_INIT(mSignature, aSignature);
@ -1084,6 +1109,8 @@ public:
{
Telemetry::Accumulate(Telemetry::WEBCRYPTO_ALG, TA_RSASSA_PKCS1);
CHECK_KEY_ALGORITHM(aKey.Algorithm(), WEBCRYPTO_ALG_RSASSA_PKCS1);
ATTEMPT_BUFFER_INIT(mData, aData);
if (!aSign) {
ATTEMPT_BUFFER_INIT(mSignature, aSignature);
@ -2289,6 +2316,8 @@ public:
void Init(JSContext* aCx, const ObjectOrString& aAlgorithm, CryptoKey& aKey,
uint32_t aLength)
{
CHECK_KEY_ALGORITHM(aKey.Algorithm(), WEBCRYPTO_ALG_PBKDF2);
// Check that we got a symmetric key
if (mSymKey.Length() == 0) {
mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
@ -2446,6 +2475,8 @@ public:
void Init(JSContext* aCx, const ObjectOrString& aAlgorithm, CryptoKey& aKey)
{
CHECK_KEY_ALGORITHM(aKey.Algorithm(), WEBCRYPTO_ALG_ECDH);
// Check that we have a private key.
if (!mPrivKey) {
mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
@ -2476,14 +2507,7 @@ public:
}
nsRefPtr<KeyAlgorithm> publicAlgorithm = publicKey->Algorithm();
// Given public key must be an ECDH key.
nsString algName;
publicAlgorithm->GetName(algName);
if (!algName.EqualsLiteral(WEBCRYPTO_ALG_ECDH)) {
mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
return;
}
CHECK_KEY_ALGORITHM(publicAlgorithm, WEBCRYPTO_ALG_ECDH);
// Both keys must use the same named curve.
nsString curve1, curve2;

View File

@ -1882,6 +1882,43 @@ TestArray.addTest(
.then(complete(that), error(that));
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"Test that we check keys before using them for encryption/signatures",
function() {
var that = this;
function doCheckRSASSA() {
var alg = {name: "HMAC", hash: {name: "SHA-1"}};
function doSign(x) {
return crypto.subtle.sign("RSASSA-PKCS1-v1_5", x, new Uint8Array());
}
return crypto.subtle.generateKey(alg, false, ["sign"]).then(doSign);
}
function doCheckRSAES() {
var alg = {
name: "RSAES-PKCS1-v1_5",
modulusLength: 1024,
publicExponent: new Uint8Array([0x01, 0x00, 0x01])
};
function doEncrypt(x) {
var alg = {name: "RSA-OAEP", hash: "SHA-1"};
return crypto.subtle.encrypt(alg, x.publicKey, new Uint8Array());
}
return crypto.subtle.generateKey(alg, false, ["encrypt"]).then(doEncrypt);
}
doCheckRSASSA().then(error(that), function () {
doCheckRSAES().then(error(that), complete(that));
});
}
);
/*]]>*/</script>
</head>