2 * Copyright (C) 2013 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include "modules/crypto/NormalizeAlgorithm.h"
34 #include "bindings/v8/Dictionary.h"
35 #include "platform/CryptoResult.h"
36 #include "platform/NotImplemented.h"
37 #include "public/platform/WebCryptoAlgorithmParams.h"
38 #include "public/platform/WebString.h"
39 #include "wtf/ArrayBuffer.h"
40 #include "wtf/ArrayBufferView.h"
41 #include "wtf/MathExtras.h"
42 #include "wtf/Uint8Array.h"
43 #include "wtf/Vector.h"
44 #include "wtf/text/StringBuilder.h"
51 struct AlgorithmNameMapping {
52 // Must be an upper case ASCII string.
53 const char* const algorithmName;
54 // Must be strlen(algorithmName).
55 unsigned char algorithmNameLength;
56 blink::WebCryptoAlgorithmId algorithmId;
59 bool operator<(const AlgorithmNameMapping&) const;
63 // Must be sorted by length, and then by reverse string.
64 // Also all names must be upper case ASCII.
65 const AlgorithmNameMapping algorithmNameMappings[] = {
66 {"HMAC", 4, blink::WebCryptoAlgorithmIdHmac},
67 {"SHA-1", 5, blink::WebCryptoAlgorithmIdSha1},
68 {"AES-KW", 6, blink::WebCryptoAlgorithmIdAesKw},
69 {"SHA-512", 7, blink::WebCryptoAlgorithmIdSha512},
70 {"SHA-384", 7, blink::WebCryptoAlgorithmIdSha384},
71 {"SHA-256", 7, blink::WebCryptoAlgorithmIdSha256},
72 {"AES-CBC", 7, blink::WebCryptoAlgorithmIdAesCbc},
73 {"AES-GCM", 7, blink::WebCryptoAlgorithmIdAesGcm},
74 {"AES-CTR", 7, blink::WebCryptoAlgorithmIdAesCtr},
75 {"RSAES-PKCS1-V1_5", 16, blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5},
76 {"RSASSA-PKCS1-V1_5", 17, blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5},
79 typedef char ParamsTypeOrUndefined;
80 const ParamsTypeOrUndefined Undefined = -1;
82 struct AlgorithmInfo {
83 // The canonical (case-sensitive) name for the algorithm.
86 // A map from the operation to the expected parameter type of the algorithm.
87 // If an operation is not applicable for the algorithm, set to Undefined.
88 const ParamsTypeOrUndefined operationToParamsType[LastAlgorithmOperation + 1];
91 // A mapping from the algorithm ID to information about the algorithm.
92 const AlgorithmInfo algorithmIdToInfo[] = {
95 blink::WebCryptoAlgorithmParamsTypeAesCbcParams, // Encrypt
96 blink::WebCryptoAlgorithmParamsTypeAesCbcParams, // Decrypt
100 blink::WebCryptoAlgorithmParamsTypeAesKeyGenParams, // GenerateKey
101 blink::WebCryptoAlgorithmParamsTypeNone, // ImportKey
102 Undefined, // DeriveKey
103 Undefined, // DeriveBits
104 blink::WebCryptoAlgorithmParamsTypeAesCbcParams, // WrapKey
105 blink::WebCryptoAlgorithmParamsTypeAesCbcParams // UnwrapKey
109 Undefined, // Encrypt
110 Undefined, // Decrypt
111 blink::WebCryptoAlgorithmParamsTypeNone, // Sign
112 blink::WebCryptoAlgorithmParamsTypeNone, // Verify
114 blink::WebCryptoAlgorithmParamsTypeHmacKeyGenParams, // GenerateKey
115 blink::WebCryptoAlgorithmParamsTypeHmacImportParams, // ImportKey
116 Undefined, // DeriveKey
117 Undefined, // DeriveBits
118 Undefined, // WrapKey
119 Undefined // UnwrapKey
122 "RSASSA-PKCS1-v1_5", {
123 Undefined, // Encrypt
124 Undefined, // Decrypt
125 blink::WebCryptoAlgorithmParamsTypeNone, // Sign
126 blink::WebCryptoAlgorithmParamsTypeNone, // Verify
128 blink::WebCryptoAlgorithmParamsTypeRsaHashedKeyGenParams, // GenerateKey
129 blink::WebCryptoAlgorithmParamsTypeRsaHashedImportParams, // ImportKey
130 Undefined, // DeriveKey
131 Undefined, // DeriveBits
132 Undefined, // WrapKey
133 Undefined // UnwrapKey
136 "RSAES-PKCS1-v1_5", {
137 blink::WebCryptoAlgorithmParamsTypeNone, // Encrypt
138 blink::WebCryptoAlgorithmParamsTypeNone, // Decrypt
142 blink::WebCryptoAlgorithmParamsTypeRsaKeyGenParams, // GenerateKey
143 blink::WebCryptoAlgorithmParamsTypeNone, // ImportKey
144 Undefined, // DeriveKey
145 Undefined, // DeriveBits
146 blink::WebCryptoAlgorithmParamsTypeNone, // WrapKey
147 blink::WebCryptoAlgorithmParamsTypeNone // UnwrapKey
151 Undefined, // Encrypt
152 Undefined, // Decrypt
155 blink::WebCryptoAlgorithmParamsTypeNone, // Digest
156 Undefined, // GenerateKey
157 Undefined, // ImportKey
158 Undefined, // DeriveKey
159 Undefined, // DeriveBits
160 Undefined, // WrapKey
161 Undefined // UnwrapKey
165 Undefined, // Encrypt
166 Undefined, // Decrypt
169 blink::WebCryptoAlgorithmParamsTypeNone, // Digest
170 Undefined, // GenerateKey
171 Undefined, // ImportKey
172 Undefined, // DeriveKey
173 Undefined, // DeriveBits
174 Undefined, // WrapKey
175 Undefined // UnwrapKey
179 Undefined, // Encrypt
180 Undefined, // Decrypt
183 blink::WebCryptoAlgorithmParamsTypeNone, // Digest
184 Undefined, // GenerateKey
185 Undefined, // ImportKey
186 Undefined, // DeriveKey
187 Undefined, // DeriveBits
188 Undefined, // WrapKey
189 Undefined // UnwrapKey
193 Undefined, // Encrypt
194 Undefined, // Decrypt
197 blink::WebCryptoAlgorithmParamsTypeNone, // Digest
198 Undefined, // GenerateKey
199 Undefined, // ImportKey
200 Undefined, // DeriveKey
201 Undefined, // DeriveBits
202 Undefined, // WrapKey
203 Undefined // UnwrapKey
207 blink::WebCryptoAlgorithmParamsTypeAesGcmParams, // Encrypt
208 blink::WebCryptoAlgorithmParamsTypeAesGcmParams, // Decrypt
212 blink::WebCryptoAlgorithmParamsTypeAesKeyGenParams, // GenerateKey
213 blink::WebCryptoAlgorithmParamsTypeNone, // ImportKey
214 Undefined, // DeriveKey
215 Undefined, // DeriveBits
216 blink::WebCryptoAlgorithmParamsTypeAesGcmParams, // WrapKey
217 blink::WebCryptoAlgorithmParamsTypeAesGcmParams // UnwrapKey
222 Undefined, // Encrypt
223 Undefined, // Decrypt
227 Undefined, // GenerateKey
228 Undefined, // ImportKey
229 Undefined, // DeriveKey
230 Undefined, // DeriveBits
231 Undefined, // WrapKey
232 Undefined // UnwrapKey
236 blink::WebCryptoAlgorithmParamsTypeAesCtrParams, // Encrypt
237 blink::WebCryptoAlgorithmParamsTypeAesCtrParams, // Decrypt
241 blink::WebCryptoAlgorithmParamsTypeAesKeyGenParams, // GenerateKey
242 blink::WebCryptoAlgorithmParamsTypeNone, // ImportKey
243 Undefined, // DeriveKey
244 Undefined, // DeriveBits
245 blink::WebCryptoAlgorithmParamsTypeAesCtrParams, // WrapKey
246 blink::WebCryptoAlgorithmParamsTypeAesCtrParams // UnwrapKey
250 Undefined, // Encrypt
251 Undefined, // Decrypt
255 blink::WebCryptoAlgorithmParamsTypeAesKeyGenParams, // GenerateKey
256 blink::WebCryptoAlgorithmParamsTypeNone, // ImportKey
257 Undefined, // DeriveKey
258 Undefined, // DeriveBits
259 blink::WebCryptoAlgorithmParamsTypeNone, // WrapKey
260 blink::WebCryptoAlgorithmParamsTypeNone // UnwrapKey
265 // Initializing the algorithmIdToInfo table above depends on knowing the enum
266 // values for algorithm IDs. If those ever change, the table will need to be
268 COMPILE_ASSERT(blink::WebCryptoAlgorithmIdAesCbc == 0, AesCbc_idDoesntMatch);
269 COMPILE_ASSERT(blink::WebCryptoAlgorithmIdHmac == 1, Hmac_idDoesntMatch);
270 COMPILE_ASSERT(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 == 2, RsaSsaPkcs1v1_5_idDoesntMatch);
271 COMPILE_ASSERT(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 == 3, RsaEsPkcs1v1_5_idDoesntMatch);
272 COMPILE_ASSERT(blink::WebCryptoAlgorithmIdSha1 == 4, Sha1_idDoesntMatch);
273 COMPILE_ASSERT(blink::WebCryptoAlgorithmIdSha256 == 5, Sha256_idDoesntMatch);
274 COMPILE_ASSERT(blink::WebCryptoAlgorithmIdSha384 == 6, Sha384_idDoesntMatch);
275 COMPILE_ASSERT(blink::WebCryptoAlgorithmIdSha512 == 7, Sha512_idDoesntMatch);
276 COMPILE_ASSERT(blink::WebCryptoAlgorithmIdAesGcm == 8, AesGcm_idDoesntMatch);
277 COMPILE_ASSERT(blink::WebCryptoAlgorithmIdRsaOaep == 9, RsaOaep_idDoesntMatch);
278 COMPILE_ASSERT(blink::WebCryptoAlgorithmIdAesCtr == 10, AesCtr_idDoesntMatch);
279 COMPILE_ASSERT(blink::WebCryptoAlgorithmIdAesKw == 11, AesKw_idDoesntMatch);
280 COMPILE_ASSERT(blink::WebCryptoAlgorithmIdLast == 11, Last_idDoesntMatch);
281 COMPILE_ASSERT(10 == LastAlgorithmOperation, UpdateParamsMapping);
285 // Essentially std::is_sorted() (however that function is new to C++11).
286 template <typename Iterator>
287 bool isSorted(Iterator begin, Iterator end)
292 Iterator prev = begin;
293 Iterator cur = begin + 1;
305 bool AlgorithmNameMapping::operator<(const AlgorithmNameMapping& o) const
307 if (algorithmNameLength < o.algorithmNameLength)
309 if (algorithmNameLength > o.algorithmNameLength)
312 for (size_t i = 0; i < algorithmNameLength; ++i) {
313 size_t reverseIndex = algorithmNameLength - i - 1;
314 char c1 = algorithmName[reverseIndex];
315 char c2 = o.algorithmName[reverseIndex];
326 bool verifyAlgorithmNameMappings(const AlgorithmNameMapping* begin, const AlgorithmNameMapping* end)
328 for (const AlgorithmNameMapping* it = begin; it != end; ++it) {
329 if (it->algorithmNameLength != strlen(it->algorithmName))
331 String str(it->algorithmName, it->algorithmNameLength);
332 if (!str.containsOnlyASCII())
334 if (str.upper() != str)
338 return isSorted(begin, end);
342 template <typename CharType>
343 bool algorithmNameComparator(const AlgorithmNameMapping& a, StringImpl* b)
345 if (a.algorithmNameLength < b->length())
347 if (a.algorithmNameLength > b->length())
350 // Because the algorithm names contain many common prefixes, it is better
351 // to compare starting at the end of the string.
352 for (size_t i = 0; i < a.algorithmNameLength; ++i) {
353 size_t reverseIndex = a.algorithmNameLength - i - 1;
354 CharType c1 = a.algorithmName[reverseIndex];
355 CharType c2 = b->getCharacters<CharType>()[reverseIndex];
358 c2 = toASCIIUpper(c2);
369 bool lookupAlgorithmIdByName(const String& algorithmName, blink::WebCryptoAlgorithmId& id)
371 const AlgorithmNameMapping* begin = algorithmNameMappings;
372 const AlgorithmNameMapping* end = algorithmNameMappings + WTF_ARRAY_LENGTH(algorithmNameMappings);
374 ASSERT(verifyAlgorithmNameMappings(begin, end));
376 const AlgorithmNameMapping* it;
377 if (algorithmName.impl()->is8Bit())
378 it = std::lower_bound(begin, end, algorithmName.impl(), &algorithmNameComparator<LChar>);
380 it = std::lower_bound(begin, end, algorithmName.impl(), &algorithmNameComparator<UChar>);
385 if (it->algorithmNameLength != algorithmName.length() || !equalIgnoringCase(algorithmName, it->algorithmName))
388 id = it->algorithmId;
392 const AlgorithmInfo* lookupAlgorithmInfo(blink::WebCryptoAlgorithmId id)
394 if (id < 0 || id >= WTF_ARRAY_LENGTH(algorithmIdToInfo))
396 return &algorithmIdToInfo[id];
399 void completeWithSyntaxError(const String& message, CryptoResult* result)
401 result->completeWithError(blink::WebCryptoErrorTypeSyntax, message);
404 void completeWithNotSupportedError(const String& message, CryptoResult* result)
406 result->completeWithError(blink::WebCryptoErrorTypeNotSupported, message);
409 void completeWithDataError(const String& message, CryptoResult* result)
411 result->completeWithError(blink::WebCryptoErrorTypeData, message);
414 // ErrorContext holds a stack of string literals which describe what was
415 // happening at the time the error occurred. This is helpful because
416 // parsing of the algorithm dictionary can be recursive and it is difficult to
417 // tell what went wrong from a failure alone.
420 void add(const char* message)
422 m_messages.append(message);
427 m_messages.removeLast();
430 // Join all of the string literals into a single String.
431 String toString() const
433 if (m_messages.isEmpty())
436 StringBuilder result;
437 const char* Separator = ": ";
439 size_t length = (m_messages.size() - 1) * strlen(Separator);
440 for (size_t i = 0; i < m_messages.size(); ++i)
441 length += strlen(m_messages[i]);
442 result.reserveCapacity(length);
444 for (size_t i = 0; i < m_messages.size(); ++i) {
446 result.append(Separator, strlen(Separator));
447 result.append(m_messages[i], strlen(m_messages[i]));
450 return result.toString();
453 String toString(const char* message) const
455 ErrorContext stack(*this);
457 return stack.toString();
460 String toString(const char* message1, const char* message2) const
462 ErrorContext stack(*this);
465 return stack.toString();
469 // This inline size is large enough to avoid having to grow the Vector in
470 // the majority of cases (up to 1 nested algorithm identifier).
471 Vector<const char*, 10> m_messages;
474 // Defined by the WebCrypto spec as:
476 // typedef (ArrayBuffer or ArrayBufferView) CryptoOperationData;
478 // FIXME: Currently only supports ArrayBufferView.
479 bool getOptionalCryptoOperationData(const Dictionary& raw, const char* propertyName, bool& hasProperty, RefPtr<ArrayBufferView>& buffer, const ErrorContext& context, CryptoResult* result)
481 if (!raw.get(propertyName, buffer)) {
489 completeWithSyntaxError(context.toString(propertyName, "Not an ArrayBufferView"), result);
496 // Defined by the WebCrypto spec as:
498 // typedef (ArrayBuffer or ArrayBufferView) CryptoOperationData;
500 // FIXME: Currently only supports ArrayBufferView.
501 bool getCryptoOperationData(const Dictionary& raw, const char* propertyName, RefPtr<ArrayBufferView>& buffer, const ErrorContext& context, CryptoResult* result)
504 bool ok = getOptionalCryptoOperationData(raw, propertyName, hasProperty, buffer, context, result);
506 completeWithSyntaxError(context.toString(propertyName, "Missing required property"), result);
512 bool getUint8Array(const Dictionary& raw, const char* propertyName, RefPtr<Uint8Array>& array, const ErrorContext& context, CryptoResult* result)
514 if (!raw.get(propertyName, array) || !array) {
515 completeWithSyntaxError(context.toString(propertyName, "Missing or not a Uint8Array"), result);
521 // Defined by the WebCrypto spec as:
523 // typedef Uint8Array BigInteger;
524 bool getBigInteger(const Dictionary& raw, const char* propertyName, RefPtr<Uint8Array>& array, const ErrorContext& context, CryptoResult* result)
526 if (!getUint8Array(raw, propertyName, array, context, result))
529 if (!array->byteLength()) {
530 completeWithSyntaxError(context.toString(propertyName, "BigInteger should not be empty"), result);
534 if (!raw.get(propertyName, array) || !array) {
535 completeWithSyntaxError(context.toString(propertyName, "Missing or not a Uint8Array"), result);
541 // Gets an integer according to WebIDL's [EnforceRange].
542 bool getOptionalInteger(const Dictionary& raw, const char* propertyName, bool& hasProperty, double& value, double minValue, double maxValue, const ErrorContext& context, CryptoResult* result)
545 bool ok = raw.get(propertyName, number, hasProperty);
550 if (!ok || std::isnan(number)) {
551 completeWithSyntaxError(context.toString(propertyName, "Is not a number"), result);
555 number = trunc(number);
557 if (std::isinf(number) || number < minValue || number > maxValue) {
558 completeWithSyntaxError(context.toString(propertyName, "Outside of numeric range"), result);
566 bool getInteger(const Dictionary& raw, const char* propertyName, double& value, double minValue, double maxValue, const ErrorContext& context, CryptoResult* result)
569 if (!getOptionalInteger(raw, propertyName, hasProperty, value, minValue, maxValue, context, result))
573 completeWithSyntaxError(context.toString(propertyName, "Missing required property"), result);
580 bool getUint32(const Dictionary& raw, const char* propertyName, uint32_t& value, const ErrorContext& context, CryptoResult* result)
583 if (!getInteger(raw, propertyName, number, 0, 0xFFFFFFFF, context, result))
589 bool getUint16(const Dictionary& raw, const char* propertyName, uint16_t& value, const ErrorContext& context, CryptoResult* result)
592 if (!getInteger(raw, propertyName, number, 0, 0xFFFF, context, result))
598 bool getUint8(const Dictionary& raw, const char* propertyName, uint8_t& value, const ErrorContext& context, CryptoResult* result)
601 if (!getInteger(raw, propertyName, number, 0, 0xFF, context, result))
607 bool getOptionalUint32(const Dictionary& raw, const char* propertyName, bool& hasValue, uint32_t& value, const ErrorContext& context, CryptoResult* result)
610 if (!getOptionalInteger(raw, propertyName, hasValue, number, 0, 0xFFFFFFFF, context, result))
617 // Defined by the WebCrypto spec as:
619 // dictionary AesCbcParams : Algorithm {
620 // CryptoOperationData iv;
622 bool parseAesCbcParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, CryptoResult* result)
624 RefPtr<ArrayBufferView> iv;
625 if (!getCryptoOperationData(raw, "iv", iv, context, result))
628 if (iv->byteLength() != 16) {
629 completeWithDataError(context.toString("iv", "Must be 16 bytes"), result);
633 params = adoptPtr(new blink::WebCryptoAesCbcParams(static_cast<unsigned char*>(iv->baseAddress()), iv->byteLength()));
637 // Defined by the WebCrypto spec as:
639 // dictionary AesKeyGenParams : Algorithm {
640 // [EnforceRange] unsigned short length;
642 bool parseAesKeyGenParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, CryptoResult* result)
645 if (!getUint16(raw, "length", length, context, result))
648 params = adoptPtr(new blink::WebCryptoAesKeyGenParams(length));
652 bool parseAlgorithm(const Dictionary&, AlgorithmOperation, blink::WebCryptoAlgorithm&, ErrorContext, CryptoResult*);
654 bool parseHash(const Dictionary& raw, blink::WebCryptoAlgorithm& hash, ErrorContext context, CryptoResult* result)
657 if (!raw.get("hash", rawHash)) {
658 completeWithSyntaxError(context.toString("hash", "Missing or not a dictionary"), result);
663 return parseAlgorithm(rawHash, Digest, hash, context, result);
666 // Defined by the WebCrypto spec as:
668 // dictionary HmacImportParams : Algorithm {
669 // AlgorithmIdentifier hash;
671 bool parseHmacImportParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, CryptoResult* result)
673 blink::WebCryptoAlgorithm hash;
674 if (!parseHash(raw, hash, context, result))
677 params = adoptPtr(new blink::WebCryptoHmacImportParams(hash));
681 // Defined by the WebCrypto spec as:
683 // dictionary HmacKeyGenParams : Algorithm {
684 // AlgorithmIdentifier hash;
685 // // The length (in bits) of the key to generate. If unspecified, the
686 // // recommended length will be used, which is the size of the associated hash function's block
688 // unsigned long length;
690 bool parseHmacKeyGenParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, CryptoResult* result)
692 blink::WebCryptoAlgorithm hash;
693 if (!parseHash(raw, hash, context, result))
698 if (!getOptionalUint32(raw, "length", hasLength, length, context, result))
701 params = adoptPtr(new blink::WebCryptoHmacKeyGenParams(hash, hasLength, length));
705 // Defined by the WebCrypto spec as:
707 // dictionary RsaHashedImportParams {
708 // AlgorithmIdentifier hash;
710 bool parseRsaHashedImportParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, CryptoResult* result)
712 blink::WebCryptoAlgorithm hash;
713 if (!parseHash(raw, hash, context, result))
716 params = adoptPtr(new blink::WebCryptoRsaHashedImportParams(hash));
720 // Defined by the WebCrypto spec as:
722 // dictionary RsaKeyGenParams : Algorithm {
723 // unsigned long modulusLength;
724 // BigInteger publicExponent;
726 bool parseRsaKeyGenParams(const Dictionary& raw, uint32_t& modulusLength, RefPtr<Uint8Array>& publicExponent, const ErrorContext& context, CryptoResult* result)
728 if (!getUint32(raw, "modulusLength", modulusLength, context, result))
731 if (!getBigInteger(raw, "publicExponent", publicExponent, context, result))
737 bool parseRsaKeyGenParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, CryptoResult* result)
739 uint32_t modulusLength;
740 RefPtr<Uint8Array> publicExponent;
741 if (!parseRsaKeyGenParams(raw, modulusLength, publicExponent, context, result))
744 params = adoptPtr(new blink::WebCryptoRsaKeyGenParams(modulusLength, static_cast<const unsigned char*>(publicExponent->baseAddress()), publicExponent->byteLength()));
748 // Defined by the WebCrypto spec as:
750 // dictionary RsaHashedKeyGenParams : RsaKeyGenParams {
751 // AlgorithmIdentifier hash;
753 bool parseRsaHashedKeyGenParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, CryptoResult* result)
755 uint32_t modulusLength;
756 RefPtr<Uint8Array> publicExponent;
757 if (!parseRsaKeyGenParams(raw, modulusLength, publicExponent, context, result))
760 blink::WebCryptoAlgorithm hash;
761 if (!parseHash(raw, hash, context, result))
764 params = adoptPtr(new blink::WebCryptoRsaHashedKeyGenParams(hash, modulusLength, static_cast<const unsigned char*>(publicExponent->baseAddress()), publicExponent->byteLength()));
768 // Defined by the WebCrypto spec as:
770 // dictionary AesCtrParams : Algorithm {
771 // CryptoOperationData counter;
772 // [EnforceRange] octet length;
774 bool parseAesCtrParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, CryptoResult* result)
776 RefPtr<ArrayBufferView> counter;
777 if (!getCryptoOperationData(raw, "counter", counter, context, result))
781 if (!getUint8(raw, "length", length, context, result))
784 params = adoptPtr(new blink::WebCryptoAesCtrParams(length, static_cast<const unsigned char*>(counter->baseAddress()), counter->byteLength()));
788 // Defined by the WebCrypto spec as:
790 // dictionary AesGcmParams : Algorithm {
791 // CryptoOperationData iv;
792 // CryptoOperationData? additionalData;
793 // [EnforceRange] octet? tagLength; // May be 0-128
795 bool parseAesGcmParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, CryptoResult* result)
797 RefPtr<ArrayBufferView> iv;
798 if (!getCryptoOperationData(raw, "iv", iv, context, result))
801 bool hasAdditionalData;
802 RefPtr<ArrayBufferView> additionalData;
803 if (!getOptionalCryptoOperationData(raw, "additionalData", hasAdditionalData, additionalData, context, result))
808 if (!getOptionalInteger(raw, "tagLength", hasTagLength, tagLength, 0, 128, context, result))
811 const unsigned char* ivStart = static_cast<const unsigned char*>(iv->baseAddress());
812 unsigned ivLength = iv->byteLength();
814 const unsigned char* additionalDataStart = hasAdditionalData ? static_cast<const unsigned char*>(additionalData->baseAddress()) : 0;
815 unsigned additionalDataLength = hasAdditionalData ? additionalData->byteLength() : 0;
817 params = adoptPtr(new blink::WebCryptoAesGcmParams(ivStart, ivLength, hasAdditionalData, additionalDataStart, additionalDataLength, hasTagLength, tagLength));
821 bool parseAlgorithmParams(const Dictionary& raw, blink::WebCryptoAlgorithmParamsType type, OwnPtr<blink::WebCryptoAlgorithmParams>& params, ErrorContext& context, CryptoResult* result)
824 case blink::WebCryptoAlgorithmParamsTypeNone:
826 case blink::WebCryptoAlgorithmParamsTypeAesCbcParams:
827 context.add("AesCbcParams");
828 return parseAesCbcParams(raw, params, context, result);
829 case blink::WebCryptoAlgorithmParamsTypeAesKeyGenParams:
830 context.add("AesKeyGenParams");
831 return parseAesKeyGenParams(raw, params, context, result);
832 case blink::WebCryptoAlgorithmParamsTypeHmacImportParams:
833 context.add("HmacImportParams");
834 return parseHmacImportParams(raw, params, context, result);
835 case blink::WebCryptoAlgorithmParamsTypeHmacKeyGenParams:
836 context.add("HmacKeyGenParams");
837 return parseHmacKeyGenParams(raw, params, context, result);
838 case blink::WebCryptoAlgorithmParamsTypeRsaHashedKeyGenParams:
839 context.add("RsaHashedKeyGenParams");
840 return parseRsaHashedKeyGenParams(raw, params, context, result);
841 case blink::WebCryptoAlgorithmParamsTypeRsaHashedImportParams:
842 context.add("RsaHashedImportParams");
843 return parseRsaHashedImportParams(raw, params, context, result);
844 case blink::WebCryptoAlgorithmParamsTypeRsaKeyGenParams:
845 context.add("RsaKeyGenParams");
846 return parseRsaKeyGenParams(raw, params, context, result);
847 case blink::WebCryptoAlgorithmParamsTypeAesCtrParams:
848 context.add("AesCtrParams");
849 return parseAesCtrParams(raw, params, context, result);
850 case blink::WebCryptoAlgorithmParamsTypeAesGcmParams:
851 context.add("AesGcmParams");
852 return parseAesGcmParams(raw, params, context, result);
853 case blink::WebCryptoAlgorithmParamsTypeRsaOaepParams:
858 ASSERT_NOT_REACHED();
862 const char* operationToString(AlgorithmOperation op)
876 return "generateKey";
891 bool parseAlgorithm(const Dictionary& raw, AlgorithmOperation op, blink::WebCryptoAlgorithm& algorithm, ErrorContext context, CryptoResult* result)
893 context.add("Algorithm");
895 if (!raw.isObject()) {
896 completeWithSyntaxError(context.toString("Not an object"), result);
900 String algorithmName;
901 if (!raw.get("name", algorithmName)) {
902 completeWithSyntaxError(context.toString("name", "Missing or not a string"), result);
906 blink::WebCryptoAlgorithmId algorithmId;
907 if (!lookupAlgorithmIdByName(algorithmName, algorithmId)) {
908 // FIXME: The spec says to return a SyntaxError if the input contains
909 // any non-ASCII characters.
910 completeWithNotSupportedError(context.toString("Unrecognized name"), result);
914 // Remove the "Algorithm:" prefix for all subsequent errors.
915 context.removeLast();
917 const AlgorithmInfo* algorithmInfo = lookupAlgorithmInfo(algorithmId);
919 if (algorithmInfo->operationToParamsType[op] == Undefined) {
920 context.add(algorithmIdToName(algorithmId));
921 completeWithNotSupportedError(context.toString("Unsupported operation", operationToString(op)), result);
925 blink::WebCryptoAlgorithmParamsType paramsType = static_cast<blink::WebCryptoAlgorithmParamsType>(algorithmInfo->operationToParamsType[op]);
927 OwnPtr<blink::WebCryptoAlgorithmParams> params;
928 if (!parseAlgorithmParams(raw, paramsType, params, context, result))
931 algorithm = blink::WebCryptoAlgorithm(algorithmId, params.release());
937 bool parseAlgorithm(const Dictionary& raw, AlgorithmOperation op, blink::WebCryptoAlgorithm& algorithm, CryptoResult* result)
939 return parseAlgorithm(raw, op, algorithm, ErrorContext(), result);
942 const char* algorithmIdToName(blink::WebCryptoAlgorithmId id)
944 return lookupAlgorithmInfo(id)->name;
947 } // namespace WebCore