1 /* 2 * Copyright (C) 2013 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 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 13 * distribution. 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. 17 * 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. 29 */ 30 31 #include "config.h" 32 #include "modules/crypto/NormalizeAlgorithm.h" 33 34 #include "bindings/v8/Dictionary.h" 35 #include "platform/NotImplemented.h" 36 #include "public/platform/WebCryptoAlgorithmParams.h" 37 #include "public/platform/WebString.h" 38 #include "wtf/ArrayBuffer.h" 39 #include "wtf/ArrayBufferView.h" 40 #include "wtf/MathExtras.h" 41 #include "wtf/Uint8Array.h" 42 #include "wtf/Vector.h" 43 #include "wtf/text/StringBuilder.h" 44 #include <algorithm> 45 46 namespace WebCore { 47 48 namespace { 49 50 struct AlgorithmNameMapping { 51 // Must be an upper case ASCII string. 52 const char* const algorithmName; 53 // Must be strlen(algorithmName). 54 unsigned char algorithmNameLength; 55 blink::WebCryptoAlgorithmId algorithmId; 56 57 #if ASSERT_ENABLED 58 bool operator<(const AlgorithmNameMapping&) const; 59 #endif 60 }; 61 62 // Must be sorted by length, and then by reverse string. 63 // Also all names must be upper case ASCII. 64 const AlgorithmNameMapping algorithmNameMappings[] = { 65 {"HMAC", 4, blink::WebCryptoAlgorithmIdHmac}, 66 {"SHA-1", 5, blink::WebCryptoAlgorithmIdSha1}, 67 {"AES-KW", 6, blink::WebCryptoAlgorithmIdAesKw}, 68 {"SHA-512", 7, blink::WebCryptoAlgorithmIdSha512}, 69 {"SHA-384", 7, blink::WebCryptoAlgorithmIdSha384}, 70 {"SHA-256", 7, blink::WebCryptoAlgorithmIdSha256}, 71 {"AES-CBC", 7, blink::WebCryptoAlgorithmIdAesCbc}, 72 {"AES-GCM", 7, blink::WebCryptoAlgorithmIdAesGcm}, 73 {"AES-CTR", 7, blink::WebCryptoAlgorithmIdAesCtr}, 74 {"RSA-OAEP", 8, blink::WebCryptoAlgorithmIdRsaOaep}, 75 {"RSASSA-PKCS1-V1_5", 17, blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5}, 76 }; 77 78 #if ASSERT_ENABLED 79 80 // Essentially std::is_sorted() (however that function is new to C++11). 81 template <typename Iterator> 82 bool isSorted(Iterator begin, Iterator end) 83 { 84 if (begin == end) 85 return true; 86 87 Iterator prev = begin; 88 Iterator cur = begin + 1; 89 90 while (cur != end) { 91 if (*cur < *prev) 92 return false; 93 cur++; 94 prev++; 95 } 96 97 return true; 98 } 99 100 bool AlgorithmNameMapping::operator<(const AlgorithmNameMapping& o) const 101 { 102 if (algorithmNameLength < o.algorithmNameLength) 103 return true; 104 if (algorithmNameLength > o.algorithmNameLength) 105 return false; 106 107 for (size_t i = 0; i < algorithmNameLength; ++i) { 108 size_t reverseIndex = algorithmNameLength - i - 1; 109 char c1 = algorithmName[reverseIndex]; 110 char c2 = o.algorithmName[reverseIndex]; 111 112 if (c1 < c2) 113 return true; 114 if (c1 > c2) 115 return false; 116 } 117 118 return false; 119 } 120 121 bool verifyAlgorithmNameMappings(const AlgorithmNameMapping* begin, const AlgorithmNameMapping* end) 122 { 123 for (const AlgorithmNameMapping* it = begin; it != end; ++it) { 124 if (it->algorithmNameLength != strlen(it->algorithmName)) 125 return false; 126 String str(it->algorithmName, it->algorithmNameLength); 127 if (!str.containsOnlyASCII()) 128 return false; 129 if (str.upper() != str) 130 return false; 131 } 132 133 return isSorted(begin, end); 134 } 135 #endif 136 137 template <typename CharType> 138 bool algorithmNameComparator(const AlgorithmNameMapping& a, StringImpl* b) 139 { 140 if (a.algorithmNameLength < b->length()) 141 return true; 142 if (a.algorithmNameLength > b->length()) 143 return false; 144 145 // Because the algorithm names contain many common prefixes, it is better 146 // to compare starting at the end of the string. 147 for (size_t i = 0; i < a.algorithmNameLength; ++i) { 148 size_t reverseIndex = a.algorithmNameLength - i - 1; 149 CharType c1 = a.algorithmName[reverseIndex]; 150 CharType c2 = b->getCharacters<CharType>()[reverseIndex]; 151 if (!isASCII(c2)) 152 return false; 153 c2 = toASCIIUpper(c2); 154 155 if (c1 < c2) 156 return true; 157 if (c1 > c2) 158 return false; 159 } 160 161 return false; 162 } 163 164 bool lookupAlgorithmIdByName(const String& algorithmName, blink::WebCryptoAlgorithmId& id) 165 { 166 const AlgorithmNameMapping* begin = algorithmNameMappings; 167 const AlgorithmNameMapping* end = algorithmNameMappings + WTF_ARRAY_LENGTH(algorithmNameMappings); 168 169 ASSERT(verifyAlgorithmNameMappings(begin, end)); 170 171 const AlgorithmNameMapping* it; 172 if (algorithmName.impl()->is8Bit()) 173 it = std::lower_bound(begin, end, algorithmName.impl(), &algorithmNameComparator<LChar>); 174 else 175 it = std::lower_bound(begin, end, algorithmName.impl(), &algorithmNameComparator<UChar>); 176 177 if (it == end) 178 return false; 179 180 if (it->algorithmNameLength != algorithmName.length() || !equalIgnoringCase(algorithmName, it->algorithmName)) 181 return false; 182 183 id = it->algorithmId; 184 return true; 185 } 186 187 void setSyntaxError(const String& message, AlgorithmError* error) 188 { 189 error->errorType = blink::WebCryptoErrorTypeSyntax; 190 error->errorDetails = message; 191 } 192 193 void setNotSupportedError(const String& message, AlgorithmError* error) 194 { 195 error->errorType = blink::WebCryptoErrorTypeNotSupported; 196 error->errorDetails = message; 197 } 198 199 void setDataError(const String& message, AlgorithmError* error) 200 { 201 error->errorType = blink::WebCryptoErrorTypeData; 202 error->errorDetails = message; 203 } 204 205 // ErrorContext holds a stack of string literals which describe what was 206 // happening at the time the error occurred. This is helpful because 207 // parsing of the algorithm dictionary can be recursive and it is difficult to 208 // tell what went wrong from a failure alone. 209 class ErrorContext { 210 public: 211 void add(const char* message) 212 { 213 m_messages.append(message); 214 } 215 216 void removeLast() 217 { 218 m_messages.removeLast(); 219 } 220 221 // Join all of the string literals into a single String. 222 String toString() const 223 { 224 if (m_messages.isEmpty()) 225 return String(); 226 227 StringBuilder result; 228 const char* Separator = ": "; 229 230 size_t length = (m_messages.size() - 1) * strlen(Separator); 231 for (size_t i = 0; i < m_messages.size(); ++i) 232 length += strlen(m_messages[i]); 233 result.reserveCapacity(length); 234 235 for (size_t i = 0; i < m_messages.size(); ++i) { 236 if (i) 237 result.append(Separator, strlen(Separator)); 238 result.append(m_messages[i], strlen(m_messages[i])); 239 } 240 241 return result.toString(); 242 } 243 244 String toString(const char* message) const 245 { 246 ErrorContext stack(*this); 247 stack.add(message); 248 return stack.toString(); 249 } 250 251 String toString(const char* message1, const char* message2) const 252 { 253 ErrorContext stack(*this); 254 stack.add(message1); 255 stack.add(message2); 256 return stack.toString(); 257 } 258 259 private: 260 // This inline size is large enough to avoid having to grow the Vector in 261 // the majority of cases (up to 1 nested algorithm identifier). 262 Vector<const char*, 10> m_messages; 263 }; 264 265 // Defined by the WebCrypto spec as: 266 // 267 // typedef (ArrayBuffer or ArrayBufferView) CryptoOperationData; 268 // 269 // FIXME: Currently only supports ArrayBufferView. 270 bool getOptionalCryptoOperationData(const Dictionary& raw, const char* propertyName, bool& hasProperty, RefPtr<ArrayBufferView>& buffer, const ErrorContext& context, AlgorithmError* error) 271 { 272 if (!raw.get(propertyName, buffer)) { 273 hasProperty = false; 274 return true; 275 } 276 277 hasProperty = true; 278 279 if (!buffer) { 280 setSyntaxError(context.toString(propertyName, "Not an ArrayBufferView"), error); 281 return false; 282 } 283 284 return true; 285 } 286 287 // Defined by the WebCrypto spec as: 288 // 289 // typedef (ArrayBuffer or ArrayBufferView) CryptoOperationData; 290 // 291 // FIXME: Currently only supports ArrayBufferView. 292 bool getCryptoOperationData(const Dictionary& raw, const char* propertyName, RefPtr<ArrayBufferView>& buffer, const ErrorContext& context, AlgorithmError* error) 293 { 294 bool hasProperty; 295 bool ok = getOptionalCryptoOperationData(raw, propertyName, hasProperty, buffer, context, error); 296 if (!hasProperty) { 297 setSyntaxError(context.toString(propertyName, "Missing required property"), error); 298 return false; 299 } 300 return ok; 301 } 302 303 bool getUint8Array(const Dictionary& raw, const char* propertyName, RefPtr<Uint8Array>& array, const ErrorContext& context, AlgorithmError* error) 304 { 305 if (!raw.get(propertyName, array) || !array) { 306 setSyntaxError(context.toString(propertyName, "Missing or not a Uint8Array"), error); 307 return false; 308 } 309 return true; 310 } 311 312 // Defined by the WebCrypto spec as: 313 // 314 // typedef Uint8Array BigInteger; 315 bool getBigInteger(const Dictionary& raw, const char* propertyName, RefPtr<Uint8Array>& array, const ErrorContext& context, AlgorithmError* error) 316 { 317 if (!getUint8Array(raw, propertyName, array, context, error)) 318 return false; 319 320 if (!array->byteLength()) { 321 setSyntaxError(context.toString(propertyName, "BigInteger should not be empty"), error); 322 return false; 323 } 324 325 if (!raw.get(propertyName, array) || !array) { 326 setSyntaxError(context.toString(propertyName, "Missing or not a Uint8Array"), error); 327 return false; 328 } 329 return true; 330 } 331 332 // Gets an integer according to WebIDL's [EnforceRange]. 333 bool getOptionalInteger(const Dictionary& raw, const char* propertyName, bool& hasProperty, double& value, double minValue, double maxValue, const ErrorContext& context, AlgorithmError* error) 334 { 335 double number; 336 bool ok = raw.get(propertyName, number, hasProperty); 337 338 if (!hasProperty) 339 return true; 340 341 if (!ok || std::isnan(number)) { 342 setSyntaxError(context.toString(propertyName, "Is not a number"), error); 343 return false; 344 } 345 346 number = trunc(number); 347 348 if (std::isinf(number) || number < minValue || number > maxValue) { 349 setSyntaxError(context.toString(propertyName, "Outside of numeric range"), error); 350 return false; 351 } 352 353 value = number; 354 return true; 355 } 356 357 bool getInteger(const Dictionary& raw, const char* propertyName, double& value, double minValue, double maxValue, const ErrorContext& context, AlgorithmError* error) 358 { 359 bool hasProperty; 360 if (!getOptionalInteger(raw, propertyName, hasProperty, value, minValue, maxValue, context, error)) 361 return false; 362 363 if (!hasProperty) { 364 setSyntaxError(context.toString(propertyName, "Missing required property"), error); 365 return false; 366 } 367 368 return true; 369 } 370 371 bool getUint32(const Dictionary& raw, const char* propertyName, uint32_t& value, const ErrorContext& context, AlgorithmError* error) 372 { 373 double number; 374 if (!getInteger(raw, propertyName, number, 0, 0xFFFFFFFF, context, error)) 375 return false; 376 value = number; 377 return true; 378 } 379 380 bool getUint16(const Dictionary& raw, const char* propertyName, uint16_t& value, const ErrorContext& context, AlgorithmError* error) 381 { 382 double number; 383 if (!getInteger(raw, propertyName, number, 0, 0xFFFF, context, error)) 384 return false; 385 value = number; 386 return true; 387 } 388 389 bool getUint8(const Dictionary& raw, const char* propertyName, uint8_t& value, const ErrorContext& context, AlgorithmError* error) 390 { 391 double number; 392 if (!getInteger(raw, propertyName, number, 0, 0xFF, context, error)) 393 return false; 394 value = number; 395 return true; 396 } 397 398 bool getOptionalUint32(const Dictionary& raw, const char* propertyName, bool& hasValue, uint32_t& value, const ErrorContext& context, AlgorithmError* error) 399 { 400 double number; 401 if (!getOptionalInteger(raw, propertyName, hasValue, number, 0, 0xFFFFFFFF, context, error)) 402 return false; 403 if (hasValue) 404 value = number; 405 return true; 406 } 407 408 // Defined by the WebCrypto spec as: 409 // 410 // dictionary AesCbcParams : Algorithm { 411 // CryptoOperationData iv; 412 // }; 413 bool parseAesCbcParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, AlgorithmError* error) 414 { 415 RefPtr<ArrayBufferView> iv; 416 if (!getCryptoOperationData(raw, "iv", iv, context, error)) 417 return false; 418 419 if (iv->byteLength() != 16) { 420 setDataError(context.toString("iv", "Must be 16 bytes"), error); 421 return false; 422 } 423 424 params = adoptPtr(new blink::WebCryptoAesCbcParams(static_cast<unsigned char*>(iv->baseAddress()), iv->byteLength())); 425 return true; 426 } 427 428 // Defined by the WebCrypto spec as: 429 // 430 // dictionary AesKeyGenParams : Algorithm { 431 // [EnforceRange] unsigned short length; 432 // }; 433 bool parseAesKeyGenParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, AlgorithmError* error) 434 { 435 uint16_t length; 436 if (!getUint16(raw, "length", length, context, error)) 437 return false; 438 439 params = adoptPtr(new blink::WebCryptoAesKeyGenParams(length)); 440 return true; 441 } 442 443 bool parseAlgorithm(const Dictionary&, blink::WebCryptoOperation, blink::WebCryptoAlgorithm&, ErrorContext, AlgorithmError*); 444 445 bool parseHash(const Dictionary& raw, blink::WebCryptoAlgorithm& hash, ErrorContext context, AlgorithmError* error) 446 { 447 Dictionary rawHash; 448 if (!raw.get("hash", rawHash)) { 449 setSyntaxError(context.toString("hash", "Missing or not a dictionary"), error); 450 return false; 451 } 452 453 context.add("hash"); 454 return parseAlgorithm(rawHash, blink::WebCryptoOperationDigest, hash, context, error); 455 } 456 457 // Defined by the WebCrypto spec as: 458 // 459 // dictionary HmacImportParams : Algorithm { 460 // AlgorithmIdentifier hash; 461 // }; 462 bool parseHmacImportParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, AlgorithmError* error) 463 { 464 blink::WebCryptoAlgorithm hash; 465 if (!parseHash(raw, hash, context, error)) 466 return false; 467 468 params = adoptPtr(new blink::WebCryptoHmacImportParams(hash)); 469 return true; 470 } 471 472 // Defined by the WebCrypto spec as: 473 // 474 // dictionary HmacKeyGenParams : Algorithm { 475 // AlgorithmIdentifier hash; 476 // // The length (in bits) of the key to generate. If unspecified, the 477 // // recommended length will be used, which is the size of the associated hash function's block 478 // // size. 479 // unsigned long length; 480 // }; 481 bool parseHmacKeyGenParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, AlgorithmError* error) 482 { 483 blink::WebCryptoAlgorithm hash; 484 if (!parseHash(raw, hash, context, error)) 485 return false; 486 487 bool hasLength; 488 uint32_t length = 0; 489 if (!getOptionalUint32(raw, "length", hasLength, length, context, error)) 490 return false; 491 492 params = adoptPtr(new blink::WebCryptoHmacKeyGenParams(hash, hasLength, length)); 493 return true; 494 } 495 496 // Defined by the WebCrypto spec as: 497 // 498 // dictionary RsaHashedImportParams { 499 // AlgorithmIdentifier hash; 500 // }; 501 bool parseRsaHashedImportParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, AlgorithmError* error) 502 { 503 blink::WebCryptoAlgorithm hash; 504 if (!parseHash(raw, hash, context, error)) 505 return false; 506 507 params = adoptPtr(new blink::WebCryptoRsaHashedImportParams(hash)); 508 return true; 509 } 510 511 // Defined by the WebCrypto spec as: 512 // 513 // dictionary RsaHashedKeyGenParams : RsaKeyGenParams { 514 // AlgorithmIdentifier hash; 515 // }; 516 // 517 // dictionary RsaKeyGenParams : Algorithm { 518 // unsigned long modulusLength; 519 // BigInteger publicExponent; 520 // }; 521 bool parseRsaHashedKeyGenParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, AlgorithmError* error) 522 { 523 uint32_t modulusLength; 524 if (!getUint32(raw, "modulusLength", modulusLength, context, error)) 525 return false; 526 527 RefPtr<Uint8Array> publicExponent; 528 if (!getBigInteger(raw, "publicExponent", publicExponent, context, error)) 529 return false; 530 531 blink::WebCryptoAlgorithm hash; 532 if (!parseHash(raw, hash, context, error)) 533 return false; 534 535 params = adoptPtr(new blink::WebCryptoRsaHashedKeyGenParams(hash, modulusLength, static_cast<const unsigned char*>(publicExponent->baseAddress()), publicExponent->byteLength())); 536 return true; 537 } 538 539 // Defined by the WebCrypto spec as: 540 // 541 // dictionary AesCtrParams : Algorithm { 542 // CryptoOperationData counter; 543 // [EnforceRange] octet length; 544 // }; 545 bool parseAesCtrParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, AlgorithmError* error) 546 { 547 RefPtr<ArrayBufferView> counter; 548 if (!getCryptoOperationData(raw, "counter", counter, context, error)) 549 return false; 550 551 uint8_t length; 552 if (!getUint8(raw, "length", length, context, error)) 553 return false; 554 555 params = adoptPtr(new blink::WebCryptoAesCtrParams(length, static_cast<const unsigned char*>(counter->baseAddress()), counter->byteLength())); 556 return true; 557 } 558 559 // Defined by the WebCrypto spec as: 560 // 561 // dictionary AesGcmParams : Algorithm { 562 // CryptoOperationData iv; 563 // CryptoOperationData? additionalData; 564 // [EnforceRange] octet? tagLength; // May be 0-128 565 // } 566 bool parseAesGcmParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, AlgorithmError* error) 567 { 568 RefPtr<ArrayBufferView> iv; 569 if (!getCryptoOperationData(raw, "iv", iv, context, error)) 570 return false; 571 572 bool hasAdditionalData; 573 RefPtr<ArrayBufferView> additionalData; 574 if (!getOptionalCryptoOperationData(raw, "additionalData", hasAdditionalData, additionalData, context, error)) 575 return false; 576 577 double tagLength; 578 bool hasTagLength; 579 if (!getOptionalInteger(raw, "tagLength", hasTagLength, tagLength, 0, 128, context, error)) 580 return false; 581 582 const unsigned char* ivStart = static_cast<const unsigned char*>(iv->baseAddress()); 583 unsigned ivLength = iv->byteLength(); 584 585 const unsigned char* additionalDataStart = hasAdditionalData ? static_cast<const unsigned char*>(additionalData->baseAddress()) : 0; 586 unsigned additionalDataLength = hasAdditionalData ? additionalData->byteLength() : 0; 587 588 params = adoptPtr(new blink::WebCryptoAesGcmParams(ivStart, ivLength, hasAdditionalData, additionalDataStart, additionalDataLength, hasTagLength, tagLength)); 589 return true; 590 } 591 592 // Defined by the WebCrypto spec as: 593 // 594 // dictionary RsaOaepParams : Algorithm { 595 // CryptoOperationData? label; 596 // }; 597 bool parseRsaOaepParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, AlgorithmError* error) 598 { 599 bool hasLabel; 600 RefPtr<ArrayBufferView> label; 601 if (!getOptionalCryptoOperationData(raw, "label", hasLabel, label, context, error)) 602 return false; 603 604 const unsigned char* labelStart = hasLabel ? static_cast<const unsigned char*>(label->baseAddress()) : 0; 605 unsigned labelLength = hasLabel ? label->byteLength() : 0; 606 607 params = adoptPtr(new blink::WebCryptoRsaOaepParams(hasLabel, labelStart, labelLength)); 608 return true; 609 } 610 611 bool parseAlgorithmParams(const Dictionary& raw, blink::WebCryptoAlgorithmParamsType type, OwnPtr<blink::WebCryptoAlgorithmParams>& params, ErrorContext& context, AlgorithmError* error) 612 { 613 switch (type) { 614 case blink::WebCryptoAlgorithmParamsTypeNone: 615 return true; 616 case blink::WebCryptoAlgorithmParamsTypeAesCbcParams: 617 context.add("AesCbcParams"); 618 return parseAesCbcParams(raw, params, context, error); 619 case blink::WebCryptoAlgorithmParamsTypeAesKeyGenParams: 620 context.add("AesKeyGenParams"); 621 return parseAesKeyGenParams(raw, params, context, error); 622 case blink::WebCryptoAlgorithmParamsTypeHmacImportParams: 623 context.add("HmacImportParams"); 624 return parseHmacImportParams(raw, params, context, error); 625 case blink::WebCryptoAlgorithmParamsTypeHmacKeyGenParams: 626 context.add("HmacKeyGenParams"); 627 return parseHmacKeyGenParams(raw, params, context, error); 628 case blink::WebCryptoAlgorithmParamsTypeRsaHashedKeyGenParams: 629 context.add("RsaHashedKeyGenParams"); 630 return parseRsaHashedKeyGenParams(raw, params, context, error); 631 case blink::WebCryptoAlgorithmParamsTypeRsaHashedImportParams: 632 context.add("RsaHashedImportParams"); 633 return parseRsaHashedImportParams(raw, params, context, error); 634 case blink::WebCryptoAlgorithmParamsTypeAesCtrParams: 635 context.add("AesCtrParams"); 636 return parseAesCtrParams(raw, params, context, error); 637 case blink::WebCryptoAlgorithmParamsTypeAesGcmParams: 638 context.add("AesGcmParams"); 639 return parseAesGcmParams(raw, params, context, error); 640 case blink::WebCryptoAlgorithmParamsTypeRsaOaepParams: 641 context.add("RsaOaepParams"); 642 return parseRsaOaepParams(raw, params, context, error); 643 break; 644 } 645 ASSERT_NOT_REACHED(); 646 return false; 647 } 648 649 const char* operationToString(blink::WebCryptoOperation op) 650 { 651 switch (op) { 652 case blink::WebCryptoOperationEncrypt: 653 return "encrypt"; 654 case blink::WebCryptoOperationDecrypt: 655 return "decrypt"; 656 case blink::WebCryptoOperationSign: 657 return "sign"; 658 case blink::WebCryptoOperationVerify: 659 return "verify"; 660 case blink::WebCryptoOperationDigest: 661 return "digest"; 662 case blink::WebCryptoOperationGenerateKey: 663 return "generateKey"; 664 case blink::WebCryptoOperationImportKey: 665 return "importKey"; 666 case blink::WebCryptoOperationDeriveKey: 667 return "deriveKey"; 668 case blink::WebCryptoOperationDeriveBits: 669 return "deriveBits"; 670 case blink::WebCryptoOperationWrapKey: 671 return "wrapKey"; 672 case blink::WebCryptoOperationUnwrapKey: 673 return "unwrapKey"; 674 } 675 return 0; 676 } 677 678 bool parseAlgorithm(const Dictionary& raw, blink::WebCryptoOperation op, blink::WebCryptoAlgorithm& algorithm, ErrorContext context, AlgorithmError* error) 679 { 680 context.add("Algorithm"); 681 682 if (!raw.isObject()) { 683 setSyntaxError(context.toString("Not an object"), error); 684 return false; 685 } 686 687 String algorithmName; 688 if (!raw.get("name", algorithmName)) { 689 setSyntaxError(context.toString("name", "Missing or not a string"), error); 690 return false; 691 } 692 693 blink::WebCryptoAlgorithmId algorithmId; 694 if (!lookupAlgorithmIdByName(algorithmName, algorithmId)) { 695 // FIXME: The spec says to return a SyntaxError if the input contains 696 // any non-ASCII characters. 697 setNotSupportedError(context.toString("Unrecognized name"), error); 698 return false; 699 } 700 701 // Remove the "Algorithm:" prefix for all subsequent errors. 702 context.removeLast(); 703 704 const blink::WebCryptoAlgorithmInfo* algorithmInfo = blink::WebCryptoAlgorithm::lookupAlgorithmInfo(algorithmId); 705 706 if (algorithmInfo->operationToParamsType[op] == blink::WebCryptoAlgorithmInfo::Undefined) { 707 context.add(algorithmInfo->name); 708 setNotSupportedError(context.toString("Unsupported operation", operationToString(op)), error); 709 return false; 710 } 711 712 blink::WebCryptoAlgorithmParamsType paramsType = static_cast<blink::WebCryptoAlgorithmParamsType>(algorithmInfo->operationToParamsType[op]); 713 714 OwnPtr<blink::WebCryptoAlgorithmParams> params; 715 if (!parseAlgorithmParams(raw, paramsType, params, context, error)) 716 return false; 717 718 algorithm = blink::WebCryptoAlgorithm(algorithmId, params.release()); 719 return true; 720 } 721 722 } // namespace 723 724 bool normalizeAlgorithm(const Dictionary& raw, blink::WebCryptoOperation op, blink::WebCryptoAlgorithm& algorithm, AlgorithmError* error) 725 { 726 return parseAlgorithm(raw, op, algorithm, ErrorContext(), error); 727 } 728 729 } // namespace WebCore 730