summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/WebKit/Source/modules/crypto/NormalizeAlgorithm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/WebKit/Source/modules/crypto/NormalizeAlgorithm.cpp')
-rw-r--r--chromium/third_party/WebKit/Source/modules/crypto/NormalizeAlgorithm.cpp642
1 files changed, 406 insertions, 236 deletions
diff --git a/chromium/third_party/WebKit/Source/modules/crypto/NormalizeAlgorithm.cpp b/chromium/third_party/WebKit/Source/modules/crypto/NormalizeAlgorithm.cpp
index 2d4d62c47ef..ac51c7cbe10 100644
--- a/chromium/third_party/WebKit/Source/modules/crypto/NormalizeAlgorithm.cpp
+++ b/chromium/third_party/WebKit/Source/modules/crypto/NormalizeAlgorithm.cpp
@@ -32,190 +32,190 @@
#include "modules/crypto/NormalizeAlgorithm.h"
#include "bindings/v8/Dictionary.h"
-#include "bindings/v8/ExceptionState.h"
-#include "core/dom/ExceptionCode.h"
#include "platform/NotImplemented.h"
#include "public/platform/WebCryptoAlgorithmParams.h"
+#include "public/platform/WebString.h"
#include "wtf/ArrayBuffer.h"
#include "wtf/ArrayBufferView.h"
-#include "wtf/HashMap.h"
#include "wtf/MathExtras.h"
#include "wtf/Uint8Array.h"
#include "wtf/Vector.h"
#include "wtf/text/StringBuilder.h"
-#include "wtf/text/StringHash.h"
+#include <algorithm>
namespace WebCore {
namespace {
struct AlgorithmNameMapping {
+ // Must be an upper case ASCII string.
const char* const algorithmName;
+ // Must be strlen(algorithmName).
+ unsigned char algorithmNameLength;
blink::WebCryptoAlgorithmId algorithmId;
-};
-
-// Indicates that the algorithm doesn't support the specified operation.
-const int UnsupportedOp = -1;
-// Either UnsupportedOp, or a value from blink::WebCryptoAlgorithmParamsType
-typedef int AlgorithmParamsForOperation;
-
-struct OperationParamsMapping {
- blink::WebCryptoAlgorithmId algorithmId;
- AlgorithmOperation operation;
- AlgorithmParamsForOperation params;
+#if ASSERT_ENABLED
+ bool operator<(const AlgorithmNameMapping&) const;
+#endif
};
+// Must be sorted by length, and then by reverse string.
+// Also all names must be upper case ASCII.
const AlgorithmNameMapping algorithmNameMappings[] = {
- {"AES-CBC", blink::WebCryptoAlgorithmIdAesCbc},
- {"AES-CTR", blink::WebCryptoAlgorithmIdAesCtr},
- {"HMAC", blink::WebCryptoAlgorithmIdHmac},
- {"RSASSA-PKCS1-v1_5", blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5},
- {"RSAES-PKCS1-v1_5", blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5},
- {"SHA-1", blink::WebCryptoAlgorithmIdSha1},
- {"SHA-224", blink::WebCryptoAlgorithmIdSha224},
- {"SHA-256", blink::WebCryptoAlgorithmIdSha256},
- {"SHA-384", blink::WebCryptoAlgorithmIdSha384},
- {"SHA-512", blink::WebCryptoAlgorithmIdSha512},
- {"AES-KW", blink::WebCryptoAlgorithmIdAesKw},
+ {"HMAC", 4, blink::WebCryptoAlgorithmIdHmac},
+ {"SHA-1", 5, blink::WebCryptoAlgorithmIdSha1},
+ {"AES-KW", 6, blink::WebCryptoAlgorithmIdAesKw},
+ {"SHA-512", 7, blink::WebCryptoAlgorithmIdSha512},
+ {"SHA-384", 7, blink::WebCryptoAlgorithmIdSha384},
+ {"SHA-256", 7, blink::WebCryptoAlgorithmIdSha256},
+ {"AES-CBC", 7, blink::WebCryptoAlgorithmIdAesCbc},
+ {"AES-GCM", 7, blink::WebCryptoAlgorithmIdAesGcm},
+ {"AES-CTR", 7, blink::WebCryptoAlgorithmIdAesCtr},
+ {"RSA-OAEP", 8, blink::WebCryptoAlgorithmIdRsaOaep},
+ {"RSASSA-PKCS1-V1_5", 17, blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5},
};
-// What operations each algorithm supports, and what parameters it expects.
-const OperationParamsMapping operationParamsMappings[] = {
- // AES-CBC
- {blink::WebCryptoAlgorithmIdAesCbc, Decrypt, blink::WebCryptoAlgorithmParamsTypeAesCbcParams},
- {blink::WebCryptoAlgorithmIdAesCbc, Encrypt, blink::WebCryptoAlgorithmParamsTypeAesCbcParams},
- {blink::WebCryptoAlgorithmIdAesCbc, GenerateKey, blink::WebCryptoAlgorithmParamsTypeAesKeyGenParams},
- {blink::WebCryptoAlgorithmIdAesCbc, ImportKey, blink::WebCryptoAlgorithmParamsTypeNone},
- {blink::WebCryptoAlgorithmIdAesCbc, UnwrapKey, blink::WebCryptoAlgorithmParamsTypeAesCbcParams},
- {blink::WebCryptoAlgorithmIdAesCbc, WrapKey, blink::WebCryptoAlgorithmParamsTypeAesCbcParams},
-
- // AES-CTR
- {blink::WebCryptoAlgorithmIdAesCtr, Decrypt, blink::WebCryptoAlgorithmParamsTypeAesCtrParams},
- {blink::WebCryptoAlgorithmIdAesCtr, Encrypt, blink::WebCryptoAlgorithmParamsTypeAesCtrParams},
- {blink::WebCryptoAlgorithmIdAesCtr, GenerateKey, blink::WebCryptoAlgorithmParamsTypeAesKeyGenParams},
- {blink::WebCryptoAlgorithmIdAesCtr, ImportKey, blink::WebCryptoAlgorithmParamsTypeNone},
- {blink::WebCryptoAlgorithmIdAesCtr, UnwrapKey, blink::WebCryptoAlgorithmParamsTypeAesCtrParams},
- {blink::WebCryptoAlgorithmIdAesCtr, WrapKey, blink::WebCryptoAlgorithmParamsTypeAesCtrParams},
-
- // HMAC
- {blink::WebCryptoAlgorithmIdHmac, Sign, blink::WebCryptoAlgorithmParamsTypeHmacParams},
- {blink::WebCryptoAlgorithmIdHmac, Verify, blink::WebCryptoAlgorithmParamsTypeHmacParams},
- {blink::WebCryptoAlgorithmIdHmac, GenerateKey, blink::WebCryptoAlgorithmParamsTypeHmacKeyParams},
- {blink::WebCryptoAlgorithmIdHmac, ImportKey, blink::WebCryptoAlgorithmParamsTypeHmacParams},
-
- // RSASSA-PKCS1-v1_5
- {blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, Sign, blink::WebCryptoAlgorithmParamsTypeRsaSsaParams},
- {blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, Verify, blink::WebCryptoAlgorithmParamsTypeRsaSsaParams},
- {blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, GenerateKey, blink::WebCryptoAlgorithmParamsTypeRsaKeyGenParams},
- {blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, ImportKey, blink::WebCryptoAlgorithmParamsTypeNone},
-
- // RSAES-PKCS1-v1_5
- {blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, Encrypt, blink::WebCryptoAlgorithmParamsTypeNone},
- {blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, Decrypt, blink::WebCryptoAlgorithmParamsTypeNone},
- {blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, GenerateKey, blink::WebCryptoAlgorithmParamsTypeRsaKeyGenParams},
- {blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, ImportKey, blink::WebCryptoAlgorithmParamsTypeNone},
- {blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, WrapKey, blink::WebCryptoAlgorithmParamsTypeNone},
- {blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, UnwrapKey, blink::WebCryptoAlgorithmParamsTypeNone},
-
- // SHA-*
- {blink::WebCryptoAlgorithmIdSha1, Digest, blink::WebCryptoAlgorithmParamsTypeNone},
- {blink::WebCryptoAlgorithmIdSha224, Digest, blink::WebCryptoAlgorithmParamsTypeNone},
- {blink::WebCryptoAlgorithmIdSha256, Digest, blink::WebCryptoAlgorithmParamsTypeNone},
- {blink::WebCryptoAlgorithmIdSha384, Digest, blink::WebCryptoAlgorithmParamsTypeNone},
- {blink::WebCryptoAlgorithmIdSha512, Digest, blink::WebCryptoAlgorithmParamsTypeNone},
-
- // AES-KW
- {blink::WebCryptoAlgorithmIdAesKw, GenerateKey, blink::WebCryptoAlgorithmParamsTypeAesKeyGenParams},
- {blink::WebCryptoAlgorithmIdAesKw, ImportKey, blink::WebCryptoAlgorithmParamsTypeNone},
- {blink::WebCryptoAlgorithmIdAesKw, UnwrapKey, blink::WebCryptoAlgorithmParamsTypeNone},
- {blink::WebCryptoAlgorithmIdAesKw, WrapKey, blink::WebCryptoAlgorithmParamsTypeNone},
-};
+#if ASSERT_ENABLED
-// This structure describes an algorithm and its supported operations.
-struct AlgorithmInfo {
- AlgorithmInfo()
- : algorithmName(0)
- {
- for (size_t i = 0; i < WTF_ARRAY_LENGTH(paramsForOperation); ++i)
- paramsForOperation[i] = UnsupportedOp;
+// Essentially std::is_sorted() (however that function is new to C++11).
+template <typename Iterator>
+bool isSorted(Iterator begin, Iterator end)
+{
+ if (begin == end)
+ return true;
+
+ Iterator prev = begin;
+ Iterator cur = begin + 1;
+
+ while (cur != end) {
+ if (*cur < *prev)
+ return false;
+ cur++;
+ prev++;
}
- blink::WebCryptoAlgorithmId algorithmId;
- const char* algorithmName;
- AlgorithmParamsForOperation paramsForOperation[LastAlgorithmOperation + 1];
-};
+ return true;
+}
-// AlgorithmRegistry enumerates each of the different algorithms and its
-// parameters. This describes the same information as the static tables above,
-// but in a more convenient runtime form.
-class AlgorithmRegistry {
-public:
- static AlgorithmRegistry& instance();
+bool AlgorithmNameMapping::operator<(const AlgorithmNameMapping& o) const
+{
+ if (algorithmNameLength < o.algorithmNameLength)
+ return true;
+ if (algorithmNameLength > o.algorithmNameLength)
+ return false;
- const AlgorithmInfo* lookupAlgorithmByName(const String&) const;
- const AlgorithmInfo* lookupAlgorithmById(blink::WebCryptoAlgorithmId) const;
+ for (size_t i = 0; i < algorithmNameLength; ++i) {
+ size_t reverseIndex = algorithmNameLength - i - 1;
+ char c1 = algorithmName[reverseIndex];
+ char c2 = o.algorithmName[reverseIndex];
-private:
- AlgorithmRegistry();
+ if (c1 < c2)
+ return true;
+ if (c1 > c2)
+ return false;
+ }
- // Algorithm name to ID.
- typedef HashMap<String, blink::WebCryptoAlgorithmId, CaseFoldingHash> AlgorithmNameToIdMap;
- AlgorithmNameToIdMap m_algorithmNameToId;
+ return false;
+}
- // Algorithm ID to information.
- AlgorithmInfo m_algorithms[blink::NumberOfWebCryptoAlgorithmId];
-};
+bool verifyAlgorithmNameMappings(const AlgorithmNameMapping* begin, const AlgorithmNameMapping* end)
+{
+ for (const AlgorithmNameMapping* it = begin; it != end; ++it) {
+ if (it->algorithmNameLength != strlen(it->algorithmName))
+ return false;
+ String str(it->algorithmName, it->algorithmNameLength);
+ if (!str.containsOnlyASCII())
+ return false;
+ if (str.upper() != str)
+ return false;
+ }
+
+ return isSorted(begin, end);
+}
+#endif
-AlgorithmRegistry& AlgorithmRegistry::instance()
+template <typename CharType>
+bool algorithmNameComparator(const AlgorithmNameMapping& a, StringImpl* b)
{
- DEFINE_STATIC_LOCAL(AlgorithmRegistry, registry, ());
- return registry;
+ if (a.algorithmNameLength < b->length())
+ return true;
+ if (a.algorithmNameLength > b->length())
+ return false;
+
+ // Because the algorithm names contain many common prefixes, it is better
+ // to compare starting at the end of the string.
+ for (size_t i = 0; i < a.algorithmNameLength; ++i) {
+ size_t reverseIndex = a.algorithmNameLength - i - 1;
+ CharType c1 = a.algorithmName[reverseIndex];
+ CharType c2 = b->getCharacters<CharType>()[reverseIndex];
+ if (!isASCII(c2))
+ return false;
+ c2 = toASCIIUpper(c2);
+
+ if (c1 < c2)
+ return true;
+ if (c1 > c2)
+ return false;
+ }
+
+ return false;
}
-const AlgorithmInfo* AlgorithmRegistry::lookupAlgorithmByName(const String& algorithmName) const
+bool lookupAlgorithmIdByName(const String& algorithmName, blink::WebCryptoAlgorithmId& id)
{
- AlgorithmNameToIdMap::const_iterator it = m_algorithmNameToId.find(algorithmName);
- if (it == m_algorithmNameToId.end())
- return 0;
- return lookupAlgorithmById(it->value);
+ const AlgorithmNameMapping* begin = algorithmNameMappings;
+ const AlgorithmNameMapping* end = algorithmNameMappings + WTF_ARRAY_LENGTH(algorithmNameMappings);
+
+ ASSERT(verifyAlgorithmNameMappings(begin, end));
+
+ const AlgorithmNameMapping* it;
+ if (algorithmName.impl()->is8Bit())
+ it = std::lower_bound(begin, end, algorithmName.impl(), &algorithmNameComparator<LChar>);
+ else
+ it = std::lower_bound(begin, end, algorithmName.impl(), &algorithmNameComparator<UChar>);
+
+ if (it == end)
+ return false;
+
+ if (it->algorithmNameLength != algorithmName.length() || !equalIgnoringCase(algorithmName, it->algorithmName))
+ return false;
+
+ id = it->algorithmId;
+ return true;
}
-const AlgorithmInfo* AlgorithmRegistry::lookupAlgorithmById(blink::WebCryptoAlgorithmId algorithmId) const
+void setSyntaxError(const String& message, AlgorithmError* error)
{
- ASSERT(algorithmId >= 0 && algorithmId < WTF_ARRAY_LENGTH(m_algorithms));
- return &m_algorithms[algorithmId];
+ error->errorType = blink::WebCryptoErrorTypeSyntax;
+ error->errorDetails = message;
}
-AlgorithmRegistry::AlgorithmRegistry()
+void setNotSupportedError(const String& message, AlgorithmError* error)
{
- for (size_t i = 0; i < WTF_ARRAY_LENGTH(algorithmNameMappings); ++i) {
- const AlgorithmNameMapping& mapping = algorithmNameMappings[i];
- m_algorithmNameToId.add(mapping.algorithmName, mapping.algorithmId);
- m_algorithms[mapping.algorithmId].algorithmName = mapping.algorithmName;
- m_algorithms[mapping.algorithmId].algorithmId = mapping.algorithmId;
- }
+ error->errorType = blink::WebCryptoErrorTypeNotSupported;
+ error->errorDetails = message;
+}
- for (size_t i = 0; i < WTF_ARRAY_LENGTH(operationParamsMappings); ++i) {
- const OperationParamsMapping& mapping = operationParamsMappings[i];
- m_algorithms[mapping.algorithmId].paramsForOperation[mapping.operation] = mapping.params;
- }
+void setDataError(const String& message, AlgorithmError* error)
+{
+ error->errorType = blink::WebCryptoErrorTypeData;
+ error->errorDetails = message;
}
-// ExceptionContext holds a stack of string literals which describe what was
-// happening at the time the exception was thrown. This is helpful because
+// ErrorContext holds a stack of string literals which describe what was
+// happening at the time the error occurred. This is helpful because
// parsing of the algorithm dictionary can be recursive and it is difficult to
-// tell what went wrong from the exception type alone (TypeError).
-class ExceptionContext {
+// tell what went wrong from a failure alone.
+class ErrorContext {
public:
- explicit ExceptionContext(AlgorithmOperation op)
- : m_op(op)
+ void add(const char* message)
{
+ m_messages.append(message);
}
- void add(const char* message)
+ void removeLast()
{
- m_messages.append(message);
+ m_messages.removeLast();
}
// Join all of the string literals into a single String.
@@ -243,47 +243,94 @@ public:
String toString(const char* message) const
{
- ExceptionContext stack(*this);
+ ErrorContext stack(*this);
stack.add(message);
return stack.toString();
}
String toString(const char* message1, const char* message2) const
{
- ExceptionContext stack(*this);
+ ErrorContext stack(*this);
stack.add(message1);
stack.add(message2);
return stack.toString();
}
private:
- AlgorithmOperation m_op;
-
// This inline size is large enough to avoid having to grow the Vector in
// the majority of cases (up to 1 nested algorithm identifier).
Vector<const char*, 10> m_messages;
};
-bool getArrayBufferView(const Dictionary& raw, const char* propertyName, RefPtr<ArrayBufferView>& buffer, const ExceptionContext& context, ExceptionState& exceptionState)
+// Defined by the WebCrypto spec as:
+//
+// typedef (ArrayBuffer or ArrayBufferView) CryptoOperationData;
+//
+// FIXME: Currently only supports ArrayBufferView.
+bool getOptionalCryptoOperationData(const Dictionary& raw, const char* propertyName, bool& hasProperty, RefPtr<ArrayBufferView>& buffer, const ErrorContext& context, AlgorithmError* error)
{
- if (!raw.get(propertyName, buffer) || !buffer) {
- exceptionState.throwTypeError(context.toString(propertyName, "Missing or not a ArrayBufferView"));
+ if (!raw.get(propertyName, buffer)) {
+ hasProperty = false;
+ return true;
+ }
+
+ hasProperty = true;
+
+ if (!buffer) {
+ setSyntaxError(context.toString(propertyName, "Not an ArrayBufferView"), error);
return false;
}
+
return true;
}
-bool getUint8Array(const Dictionary& raw, const char* propertyName, RefPtr<Uint8Array>& array, const ExceptionContext& context, ExceptionState& exceptionState)
+// Defined by the WebCrypto spec as:
+//
+// typedef (ArrayBuffer or ArrayBufferView) CryptoOperationData;
+//
+// FIXME: Currently only supports ArrayBufferView.
+bool getCryptoOperationData(const Dictionary& raw, const char* propertyName, RefPtr<ArrayBufferView>& buffer, const ErrorContext& context, AlgorithmError* error)
{
+ bool hasProperty;
+ bool ok = getOptionalCryptoOperationData(raw, propertyName, hasProperty, buffer, context, error);
+ if (!hasProperty) {
+ setSyntaxError(context.toString(propertyName, "Missing required property"), error);
+ return false;
+ }
+ return ok;
+}
+
+bool getUint8Array(const Dictionary& raw, const char* propertyName, RefPtr<Uint8Array>& array, const ErrorContext& context, AlgorithmError* error)
+{
+ if (!raw.get(propertyName, array) || !array) {
+ setSyntaxError(context.toString(propertyName, "Missing or not a Uint8Array"), error);
+ return false;
+ }
+ return true;
+}
+
+// Defined by the WebCrypto spec as:
+//
+// typedef Uint8Array BigInteger;
+bool getBigInteger(const Dictionary& raw, const char* propertyName, RefPtr<Uint8Array>& array, const ErrorContext& context, AlgorithmError* error)
+{
+ if (!getUint8Array(raw, propertyName, array, context, error))
+ return false;
+
+ if (!array->byteLength()) {
+ setSyntaxError(context.toString(propertyName, "BigInteger should not be empty"), error);
+ return false;
+ }
+
if (!raw.get(propertyName, array) || !array) {
- exceptionState.throwTypeError(context.toString(propertyName, "Missing or not a Uint8Array"));
+ setSyntaxError(context.toString(propertyName, "Missing or not a Uint8Array"), error);
return false;
}
return true;
}
// Gets an integer according to WebIDL's [EnforceRange].
-bool getOptionalInteger(const Dictionary& raw, const char* propertyName, bool& hasProperty, double& value, double minValue, double maxValue, const ExceptionContext& context, ExceptionState& exceptionState)
+bool getOptionalInteger(const Dictionary& raw, const char* propertyName, bool& hasProperty, double& value, double minValue, double maxValue, const ErrorContext& context, AlgorithmError* error)
{
double number;
bool ok = raw.get(propertyName, number, hasProperty);
@@ -292,14 +339,14 @@ bool getOptionalInteger(const Dictionary& raw, const char* propertyName, bool& h
return true;
if (!ok || std::isnan(number)) {
- exceptionState.throwTypeError(context.toString(propertyName, "Is not a number"));
+ setSyntaxError(context.toString(propertyName, "Is not a number"), error);
return false;
}
number = trunc(number);
if (std::isinf(number) || number < minValue || number > maxValue) {
- exceptionState.throwTypeError(context.toString(propertyName, "Outside of numeric range"));
+ setSyntaxError(context.toString(propertyName, "Outside of numeric range"), error);
return false;
}
@@ -307,65 +354,70 @@ bool getOptionalInteger(const Dictionary& raw, const char* propertyName, bool& h
return true;
}
-bool getInteger(const Dictionary& raw, const char* propertyName, double& value, double minValue, double maxValue, const ExceptionContext& context, ExceptionState& exceptionState)
+bool getInteger(const Dictionary& raw, const char* propertyName, double& value, double minValue, double maxValue, const ErrorContext& context, AlgorithmError* error)
{
bool hasProperty;
- if (!getOptionalInteger(raw, propertyName, hasProperty, value, minValue, maxValue, context, exceptionState))
+ if (!getOptionalInteger(raw, propertyName, hasProperty, value, minValue, maxValue, context, error))
return false;
if (!hasProperty) {
- exceptionState.throwTypeError(context.toString(propertyName, "Missing required property"));
+ setSyntaxError(context.toString(propertyName, "Missing required property"), error);
return false;
}
return true;
}
-bool getUint32(const Dictionary& raw, const char* propertyName, uint32_t& value, const ExceptionContext& context, ExceptionState& exceptionState)
+bool getUint32(const Dictionary& raw, const char* propertyName, uint32_t& value, const ErrorContext& context, AlgorithmError* error)
{
double number;
- if (!getInteger(raw, propertyName, number, 0, 0xFFFFFFFF, context, exceptionState))
+ if (!getInteger(raw, propertyName, number, 0, 0xFFFFFFFF, context, error))
return false;
value = number;
return true;
}
-bool getUint16(const Dictionary& raw, const char* propertyName, uint16_t& value, const ExceptionContext& context, ExceptionState& exceptionState)
+bool getUint16(const Dictionary& raw, const char* propertyName, uint16_t& value, const ErrorContext& context, AlgorithmError* error)
{
double number;
- if (!getInteger(raw, propertyName, number, 0, 0xFFFF, context, exceptionState))
+ if (!getInteger(raw, propertyName, number, 0, 0xFFFF, context, error))
return false;
value = number;
return true;
}
-bool getUint8(const Dictionary& raw, const char* propertyName, uint8_t& value, const ExceptionContext& context, ExceptionState& exceptionState)
+bool getUint8(const Dictionary& raw, const char* propertyName, uint8_t& value, const ErrorContext& context, AlgorithmError* error)
{
double number;
- if (!getInteger(raw, propertyName, number, 0, 0xFF, context, exceptionState))
+ if (!getInteger(raw, propertyName, number, 0, 0xFF, context, error))
return false;
value = number;
return true;
}
-bool getOptionalUint32(const Dictionary& raw, const char* propertyName, bool& hasValue, uint32_t& value, const ExceptionContext& context, ExceptionState& exceptionState)
+bool getOptionalUint32(const Dictionary& raw, const char* propertyName, bool& hasValue, uint32_t& value, const ErrorContext& context, AlgorithmError* error)
{
double number;
- if (!getOptionalInteger(raw, propertyName, hasValue, number, 0, 0xFFFFFFFF, context, exceptionState))
+ if (!getOptionalInteger(raw, propertyName, hasValue, number, 0, 0xFFFFFFFF, context, error))
return false;
if (hasValue)
value = number;
return true;
}
-bool parseAesCbcParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ExceptionContext& context, ExceptionState& exceptionState)
+// Defined by the WebCrypto spec as:
+//
+// dictionary AesCbcParams : Algorithm {
+// CryptoOperationData iv;
+// };
+bool parseAesCbcParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, AlgorithmError* error)
{
RefPtr<ArrayBufferView> iv;
- if (!getArrayBufferView(raw, "iv", iv, context, exceptionState))
+ if (!getCryptoOperationData(raw, "iv", iv, context, error))
return false;
if (iv->byteLength() != 16) {
- exceptionState.throwTypeError(context.toString("iv", "Must be 16 bytes"));
+ setDataError(context.toString("iv", "Must be 16 bytes"), error);
return false;
}
@@ -373,187 +425,305 @@ bool parseAesCbcParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmPa
return true;
}
-bool parseAesKeyGenParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ExceptionContext& context, ExceptionState& exceptionState)
+// Defined by the WebCrypto spec as:
+//
+// dictionary AesKeyGenParams : Algorithm {
+// [EnforceRange] unsigned short length;
+// };
+bool parseAesKeyGenParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, AlgorithmError* error)
{
uint16_t length;
- if (!getUint16(raw, "length", length, context, exceptionState))
+ if (!getUint16(raw, "length", length, context, error))
return false;
params = adoptPtr(new blink::WebCryptoAesKeyGenParams(length));
return true;
}
-bool normalizeAlgorithm(const Dictionary&, AlgorithmOperation, blink::WebCryptoAlgorithm&, ExceptionContext, ExceptionState&);
+bool parseAlgorithm(const Dictionary&, blink::WebCryptoOperation, blink::WebCryptoAlgorithm&, ErrorContext, AlgorithmError*);
-bool parseHash(const Dictionary& raw, blink::WebCryptoAlgorithm& hash, ExceptionContext context, ExceptionState& exceptionState)
+bool parseHash(const Dictionary& raw, blink::WebCryptoAlgorithm& hash, ErrorContext context, AlgorithmError* error)
{
Dictionary rawHash;
if (!raw.get("hash", rawHash)) {
- exceptionState.throwTypeError(context.toString("hash", "Missing or not a dictionary"));
+ setSyntaxError(context.toString("hash", "Missing or not a dictionary"), error);
return false;
}
context.add("hash");
- return normalizeAlgorithm(rawHash, Digest, hash, context, exceptionState);
+ return parseAlgorithm(rawHash, blink::WebCryptoOperationDigest, hash, context, error);
}
-bool parseHmacParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ExceptionContext& context, ExceptionState& exceptionState)
+// Defined by the WebCrypto spec as:
+//
+// dictionary HmacImportParams : Algorithm {
+// AlgorithmIdentifier hash;
+// };
+bool parseHmacImportParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, AlgorithmError* error)
{
blink::WebCryptoAlgorithm hash;
- if (!parseHash(raw, hash, context, exceptionState))
+ if (!parseHash(raw, hash, context, error))
return false;
- params = adoptPtr(new blink::WebCryptoHmacParams(hash));
+ params = adoptPtr(new blink::WebCryptoHmacImportParams(hash));
return true;
}
-bool parseHmacKeyParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ExceptionContext& context, ExceptionState& exceptionState)
+// Defined by the WebCrypto spec as:
+//
+// dictionary HmacKeyGenParams : Algorithm {
+// AlgorithmIdentifier hash;
+// // The length (in bits) of the key to generate. If unspecified, the
+// // recommended length will be used, which is the size of the associated hash function's block
+// // size.
+// unsigned long length;
+// };
+bool parseHmacKeyGenParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, AlgorithmError* error)
{
blink::WebCryptoAlgorithm hash;
- if (!parseHash(raw, hash, context, exceptionState))
+ if (!parseHash(raw, hash, context, error))
return false;
bool hasLength;
uint32_t length = 0;
- if (!getOptionalUint32(raw, "length", hasLength, length, context, exceptionState))
+ if (!getOptionalUint32(raw, "length", hasLength, length, context, error))
return false;
- params = adoptPtr(new blink::WebCryptoHmacKeyParams(hash, hasLength, length));
+ params = adoptPtr(new blink::WebCryptoHmacKeyGenParams(hash, hasLength, length));
return true;
}
-bool parseRsaSsaParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ExceptionContext& context, ExceptionState& exceptionState)
+// Defined by the WebCrypto spec as:
+//
+// dictionary RsaHashedImportParams {
+// AlgorithmIdentifier hash;
+// };
+bool parseRsaHashedImportParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, AlgorithmError* error)
{
blink::WebCryptoAlgorithm hash;
- if (!parseHash(raw, hash, context, exceptionState))
+ if (!parseHash(raw, hash, context, error))
return false;
- params = adoptPtr(new blink::WebCryptoRsaSsaParams(hash));
+ params = adoptPtr(new blink::WebCryptoRsaHashedImportParams(hash));
return true;
}
-bool parseRsaKeyGenParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ExceptionContext& context, ExceptionState& exceptionState)
+// Defined by the WebCrypto spec as:
+//
+// dictionary RsaHashedKeyGenParams : RsaKeyGenParams {
+// AlgorithmIdentifier hash;
+// };
+//
+// dictionary RsaKeyGenParams : Algorithm {
+// unsigned long modulusLength;
+// BigInteger publicExponent;
+// };
+bool parseRsaHashedKeyGenParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, AlgorithmError* error)
{
uint32_t modulusLength;
- if (!getUint32(raw, "modulusLength", modulusLength, context, exceptionState))
+ if (!getUint32(raw, "modulusLength", modulusLength, context, error))
return false;
RefPtr<Uint8Array> publicExponent;
- if (!getUint8Array(raw, "publicExponent", publicExponent, context, exceptionState))
+ if (!getBigInteger(raw, "publicExponent", publicExponent, context, error))
return false;
- params = adoptPtr(new blink::WebCryptoRsaKeyGenParams(modulusLength, static_cast<const unsigned char*>(publicExponent->baseAddress()), publicExponent->byteLength()));
+ blink::WebCryptoAlgorithm hash;
+ if (!parseHash(raw, hash, context, error))
+ return false;
+
+ params = adoptPtr(new blink::WebCryptoRsaHashedKeyGenParams(hash, modulusLength, static_cast<const unsigned char*>(publicExponent->baseAddress()), publicExponent->byteLength()));
return true;
}
-bool parseAesCtrParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ExceptionContext& context, ExceptionState& es)
+// Defined by the WebCrypto spec as:
+//
+// dictionary AesCtrParams : Algorithm {
+// CryptoOperationData counter;
+// [EnforceRange] octet length;
+// };
+bool parseAesCtrParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, AlgorithmError* error)
{
- RefPtr<Uint8Array> counter;
- if (!getUint8Array(raw, "counter", counter, context, es))
+ RefPtr<ArrayBufferView> counter;
+ if (!getCryptoOperationData(raw, "counter", counter, context, error))
return false;
uint8_t length;
- if (!getUint8(raw, "length", length, context, es))
+ if (!getUint8(raw, "length", length, context, error))
return false;
params = adoptPtr(new blink::WebCryptoAesCtrParams(length, static_cast<const unsigned char*>(counter->baseAddress()), counter->byteLength()));
return true;
}
-bool parseAlgorithmParams(const Dictionary& raw, blink::WebCryptoAlgorithmParamsType type, OwnPtr<blink::WebCryptoAlgorithmParams>& params, ExceptionContext& context, ExceptionState& exceptionState)
+// Defined by the WebCrypto spec as:
+//
+// dictionary AesGcmParams : Algorithm {
+// CryptoOperationData iv;
+// CryptoOperationData? additionalData;
+// [EnforceRange] octet? tagLength; // May be 0-128
+// }
+bool parseAesGcmParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, AlgorithmError* error)
+{
+ RefPtr<ArrayBufferView> iv;
+ if (!getCryptoOperationData(raw, "iv", iv, context, error))
+ return false;
+
+ bool hasAdditionalData;
+ RefPtr<ArrayBufferView> additionalData;
+ if (!getOptionalCryptoOperationData(raw, "additionalData", hasAdditionalData, additionalData, context, error))
+ return false;
+
+ double tagLength;
+ bool hasTagLength;
+ if (!getOptionalInteger(raw, "tagLength", hasTagLength, tagLength, 0, 128, context, error))
+ return false;
+
+ const unsigned char* ivStart = static_cast<const unsigned char*>(iv->baseAddress());
+ unsigned ivLength = iv->byteLength();
+
+ const unsigned char* additionalDataStart = hasAdditionalData ? static_cast<const unsigned char*>(additionalData->baseAddress()) : 0;
+ unsigned additionalDataLength = hasAdditionalData ? additionalData->byteLength() : 0;
+
+ params = adoptPtr(new blink::WebCryptoAesGcmParams(ivStart, ivLength, hasAdditionalData, additionalDataStart, additionalDataLength, hasTagLength, tagLength));
+ return true;
+}
+
+// Defined by the WebCrypto spec as:
+//
+// dictionary RsaOaepParams : Algorithm {
+// CryptoOperationData? label;
+// };
+bool parseRsaOaepParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, AlgorithmError* error)
+{
+ bool hasLabel;
+ RefPtr<ArrayBufferView> label;
+ if (!getOptionalCryptoOperationData(raw, "label", hasLabel, label, context, error))
+ return false;
+
+ const unsigned char* labelStart = hasLabel ? static_cast<const unsigned char*>(label->baseAddress()) : 0;
+ unsigned labelLength = hasLabel ? label->byteLength() : 0;
+
+ params = adoptPtr(new blink::WebCryptoRsaOaepParams(hasLabel, labelStart, labelLength));
+ return true;
+}
+
+bool parseAlgorithmParams(const Dictionary& raw, blink::WebCryptoAlgorithmParamsType type, OwnPtr<blink::WebCryptoAlgorithmParams>& params, ErrorContext& context, AlgorithmError* error)
{
switch (type) {
case blink::WebCryptoAlgorithmParamsTypeNone:
return true;
case blink::WebCryptoAlgorithmParamsTypeAesCbcParams:
context.add("AesCbcParams");
- return parseAesCbcParams(raw, params, context, exceptionState);
+ return parseAesCbcParams(raw, params, context, error);
case blink::WebCryptoAlgorithmParamsTypeAesKeyGenParams:
context.add("AesKeyGenParams");
- return parseAesKeyGenParams(raw, params, context, exceptionState);
- case blink::WebCryptoAlgorithmParamsTypeHmacParams:
- context.add("HmacParams");
- return parseHmacParams(raw, params, context, exceptionState);
- case blink::WebCryptoAlgorithmParamsTypeHmacKeyParams:
- context.add("HmacKeyParams");
- return parseHmacKeyParams(raw, params, context, exceptionState);
- case blink::WebCryptoAlgorithmParamsTypeRsaSsaParams:
- context.add("RsaSSaParams");
- return parseRsaSsaParams(raw, params, context, exceptionState);
- case blink::WebCryptoAlgorithmParamsTypeRsaKeyGenParams:
- context.add("RsaKeyGenParams");
- return parseRsaKeyGenParams(raw, params, context, exceptionState);
+ return parseAesKeyGenParams(raw, params, context, error);
+ case blink::WebCryptoAlgorithmParamsTypeHmacImportParams:
+ context.add("HmacImportParams");
+ return parseHmacImportParams(raw, params, context, error);
+ case blink::WebCryptoAlgorithmParamsTypeHmacKeyGenParams:
+ context.add("HmacKeyGenParams");
+ return parseHmacKeyGenParams(raw, params, context, error);
+ case blink::WebCryptoAlgorithmParamsTypeRsaHashedKeyGenParams:
+ context.add("RsaHashedKeyGenParams");
+ return parseRsaHashedKeyGenParams(raw, params, context, error);
+ case blink::WebCryptoAlgorithmParamsTypeRsaHashedImportParams:
+ context.add("RsaHashedImportParams");
+ return parseRsaHashedImportParams(raw, params, context, error);
case blink::WebCryptoAlgorithmParamsTypeAesCtrParams:
context.add("AesCtrParams");
- return parseAesCtrParams(raw, params, context, exceptionState);
+ return parseAesCtrParams(raw, params, context, error);
case blink::WebCryptoAlgorithmParamsTypeAesGcmParams:
+ context.add("AesGcmParams");
+ return parseAesGcmParams(raw, params, context, error);
case blink::WebCryptoAlgorithmParamsTypeRsaOaepParams:
- // TODO
- notImplemented();
+ context.add("RsaOaepParams");
+ return parseRsaOaepParams(raw, params, context, error);
break;
}
ASSERT_NOT_REACHED();
return false;
}
-const AlgorithmInfo* algorithmInfo(const Dictionary& raw, const ExceptionContext& context, ExceptionState& exceptionState)
+const char* operationToString(blink::WebCryptoOperation op)
{
+ switch (op) {
+ case blink::WebCryptoOperationEncrypt:
+ return "encrypt";
+ case blink::WebCryptoOperationDecrypt:
+ return "decrypt";
+ case blink::WebCryptoOperationSign:
+ return "sign";
+ case blink::WebCryptoOperationVerify:
+ return "verify";
+ case blink::WebCryptoOperationDigest:
+ return "digest";
+ case blink::WebCryptoOperationGenerateKey:
+ return "generateKey";
+ case blink::WebCryptoOperationImportKey:
+ return "importKey";
+ case blink::WebCryptoOperationDeriveKey:
+ return "deriveKey";
+ case blink::WebCryptoOperationDeriveBits:
+ return "deriveBits";
+ case blink::WebCryptoOperationWrapKey:
+ return "wrapKey";
+ case blink::WebCryptoOperationUnwrapKey:
+ return "unwrapKey";
+ }
+ return 0;
+}
+
+bool parseAlgorithm(const Dictionary& raw, blink::WebCryptoOperation op, blink::WebCryptoAlgorithm& algorithm, ErrorContext context, AlgorithmError* error)
+{
+ context.add("Algorithm");
+
if (!raw.isObject()) {
- exceptionState.throwTypeError(context.toString("Not an object"));
- return 0;
+ setSyntaxError(context.toString("Not an object"), error);
+ return false;
}
String algorithmName;
if (!raw.get("name", algorithmName)) {
- exceptionState.throwTypeError(context.toString("name", "Missing or not a string"));
- return 0;
+ setSyntaxError(context.toString("name", "Missing or not a string"), error);
+ return false;
}
- const AlgorithmInfo* info = AlgorithmRegistry::instance().lookupAlgorithmByName(algorithmName);
- if (!info) {
- exceptionState.throwDOMException(NotSupportedError, context.toString("Unrecognized algorithm name"));
- return 0;
+ blink::WebCryptoAlgorithmId algorithmId;
+ if (!lookupAlgorithmIdByName(algorithmName, algorithmId)) {
+ // FIXME: The spec says to return a SyntaxError if the input contains
+ // any non-ASCII characters.
+ setNotSupportedError(context.toString("Unrecognized name"), error);
+ return false;
}
- return info;
-}
-
-// This implementation corresponds with:
-// http://www.w3.org/TR/WebCryptoAPI/#algorithm-normalizing-rules
-bool normalizeAlgorithm(const Dictionary& raw, AlgorithmOperation op, blink::WebCryptoAlgorithm& algorithm, ExceptionContext context, ExceptionState& exceptionState)
-{
- context.add("Algorithm");
-
- const AlgorithmInfo* info = algorithmInfo(raw, context, exceptionState);
- if (!info)
- return false;
+ // Remove the "Algorithm:" prefix for all subsequent errors.
+ context.removeLast();
- context.add(info->algorithmName);
+ const blink::WebCryptoAlgorithmInfo* algorithmInfo = blink::WebCryptoAlgorithm::lookupAlgorithmInfo(algorithmId);
- if (info->paramsForOperation[op] == UnsupportedOp) {
- exceptionState.throwDOMException(NotSupportedError, context.toString("Unsupported operation"));
+ if (algorithmInfo->operationToParamsType[op] == blink::WebCryptoAlgorithmInfo::Undefined) {
+ context.add(algorithmInfo->name);
+ setNotSupportedError(context.toString("Unsupported operation", operationToString(op)), error);
return false;
}
- blink::WebCryptoAlgorithmParamsType paramsType = static_cast<blink::WebCryptoAlgorithmParamsType>(info->paramsForOperation[op]);
+ blink::WebCryptoAlgorithmParamsType paramsType = static_cast<blink::WebCryptoAlgorithmParamsType>(algorithmInfo->operationToParamsType[op]);
+
OwnPtr<blink::WebCryptoAlgorithmParams> params;
- if (!parseAlgorithmParams(raw, paramsType, params, context, exceptionState))
+ if (!parseAlgorithmParams(raw, paramsType, params, context, error))
return false;
- algorithm = blink::WebCryptoAlgorithm(info->algorithmId, params.release());
+ algorithm = blink::WebCryptoAlgorithm(algorithmId, params.release());
return true;
}
} // namespace
-bool normalizeAlgorithm(const Dictionary& raw, AlgorithmOperation op, blink::WebCryptoAlgorithm& algorithm, ExceptionState& exceptionState)
-{
- return normalizeAlgorithm(raw, op, algorithm, ExceptionContext(op), exceptionState);
-}
-
-const char* algorithmIdToName(blink::WebCryptoAlgorithmId id)
+bool normalizeAlgorithm(const Dictionary& raw, blink::WebCryptoOperation op, blink::WebCryptoAlgorithm& algorithm, AlgorithmError* error)
{
- return AlgorithmRegistry::instance().lookupAlgorithmById(id)->algorithmName;
+ return parseAlgorithm(raw, op, algorithm, ErrorContext(), error);
}
} // namespace WebCore