Home | History | Annotate | Download | only in test
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/logging.h"
      6 #include "base/stl_util.h"
      7 #include "content/child/webcrypto/algorithm_dispatch.h"
      8 #include "content/child/webcrypto/crypto_data.h"
      9 #include "content/child/webcrypto/status.h"
     10 #include "content/child/webcrypto/test/test_helpers.h"
     11 #include "content/child/webcrypto/webcrypto_util.h"
     12 #include "testing/gtest/include/gtest/gtest.h"
     13 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
     14 #include "third_party/WebKit/public/platform/WebCryptoKey.h"
     15 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
     16 
     17 namespace content {
     18 
     19 namespace webcrypto {
     20 
     21 namespace {
     22 
     23 // Helper for ImportJwkRsaFailures. Restores the JWK JSON
     24 // dictionary to a good state
     25 void RestoreJwkRsaDictionary(base::DictionaryValue* dict) {
     26   dict->Clear();
     27   dict->SetString("kty", "RSA");
     28   dict->SetString("alg", "RS256");
     29   dict->SetString("use", "sig");
     30   dict->SetBoolean("ext", false);
     31   dict->SetString(
     32       "n",
     33       "qLOyhK-OtQs4cDSoYPFGxJGfMYdjzWxVmMiuSBGh4KvEx-CwgtaTpef87Wdc9GaFEncsDLxk"
     34       "p0LGxjD1M8jMcvYq6DPEC_JYQumEu3i9v5fAEH1VvbZi9cTg-rmEXLUUjvc5LdOq_5OuHmtm"
     35       "e7PUJHYW1PW6ENTP0ibeiNOfFvs");
     36   dict->SetString("e", "AQAB");
     37 }
     38 
     39 TEST(WebCryptoRsaSsaTest, ImportExportSpki) {
     40   // Passing case: Import a valid RSA key in SPKI format.
     41   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
     42   ASSERT_EQ(Status::Success(),
     43             ImportKey(blink::WebCryptoKeyFormatSpki,
     44                       CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
     45                       CreateRsaHashedImportAlgorithm(
     46                           blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
     47                           blink::WebCryptoAlgorithmIdSha256),
     48                       true,
     49                       blink::WebCryptoKeyUsageVerify,
     50                       &key));
     51   EXPECT_TRUE(key.handle());
     52   EXPECT_EQ(blink::WebCryptoKeyTypePublic, key.type());
     53   EXPECT_TRUE(key.extractable());
     54   EXPECT_EQ(blink::WebCryptoKeyUsageVerify, key.usages());
     55   EXPECT_EQ(kModulusLengthBits,
     56             key.algorithm().rsaHashedParams()->modulusLengthBits());
     57   EXPECT_BYTES_EQ_HEX(
     58       "010001",
     59       CryptoData(key.algorithm().rsaHashedParams()->publicExponent()));
     60 
     61   // Failing case: Empty SPKI data
     62   EXPECT_EQ(
     63       Status::ErrorImportEmptyKeyData(),
     64       ImportKey(blink::WebCryptoKeyFormatSpki,
     65                 CryptoData(std::vector<uint8_t>()),
     66                 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
     67                 true,
     68                 blink::WebCryptoKeyUsageVerify,
     69                 &key));
     70 
     71   // Failing case: Bad DER encoding.
     72   EXPECT_EQ(
     73       Status::DataError(),
     74       ImportKey(blink::WebCryptoKeyFormatSpki,
     75                 CryptoData(HexStringToBytes("618333c4cb")),
     76                 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
     77                 true,
     78                 blink::WebCryptoKeyUsageVerify,
     79                 &key));
     80 
     81   // Failing case: Import RSA key but provide an inconsistent input algorithm.
     82   EXPECT_EQ(Status::ErrorUnsupportedImportKeyFormat(),
     83             ImportKey(blink::WebCryptoKeyFormatSpki,
     84                       CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
     85                       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
     86                       true,
     87                       blink::WebCryptoKeyUsageEncrypt,
     88                       &key));
     89 
     90   // Passing case: Export a previously imported RSA public key in SPKI format
     91   // and compare to original data.
     92   std::vector<uint8_t> output;
     93   ASSERT_EQ(Status::Success(),
     94             ExportKey(blink::WebCryptoKeyFormatSpki, key, &output));
     95   EXPECT_BYTES_EQ_HEX(kPublicKeySpkiDerHex, output);
     96 
     97   // Failing case: Try to export a previously imported RSA public key in raw
     98   // format (not allowed for a public key).
     99   EXPECT_EQ(Status::ErrorUnsupportedExportKeyFormat(),
    100             ExportKey(blink::WebCryptoKeyFormatRaw, key, &output));
    101 
    102   // Failing case: Try to export a non-extractable key
    103   ASSERT_EQ(Status::Success(),
    104             ImportKey(blink::WebCryptoKeyFormatSpki,
    105                       CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
    106                       CreateRsaHashedImportAlgorithm(
    107                           blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
    108                           blink::WebCryptoAlgorithmIdSha256),
    109                       false,
    110                       blink::WebCryptoKeyUsageVerify,
    111                       &key));
    112   EXPECT_TRUE(key.handle());
    113   EXPECT_FALSE(key.extractable());
    114   EXPECT_EQ(Status::ErrorKeyNotExtractable(),
    115             ExportKey(blink::WebCryptoKeyFormatSpki, key, &output));
    116 
    117   // TODO(eroman): Failing test: Import a SPKI with an unrecognized hash OID
    118   // TODO(eroman): Failing test: Import a SPKI with invalid algorithm params
    119   // TODO(eroman): Failing test: Import a SPKI with inconsistent parameters
    120   // (e.g. SHA-1 in OID, SHA-256 in params)
    121   // TODO(eroman): Failing test: Import a SPKI for RSA-SSA, but with params
    122   // as OAEP/PSS
    123 }
    124 
    125 TEST(WebCryptoRsaSsaTest, ImportExportPkcs8) {
    126   if (!SupportsRsaPrivateKeyImport())
    127     return;
    128 
    129   // Passing case: Import a valid RSA key in PKCS#8 format.
    130   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
    131   ASSERT_EQ(Status::Success(),
    132             ImportKey(blink::WebCryptoKeyFormatPkcs8,
    133                       CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
    134                       CreateRsaHashedImportAlgorithm(
    135                           blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
    136                           blink::WebCryptoAlgorithmIdSha1),
    137                       true,
    138                       blink::WebCryptoKeyUsageSign,
    139                       &key));
    140   EXPECT_TRUE(key.handle());
    141   EXPECT_EQ(blink::WebCryptoKeyTypePrivate, key.type());
    142   EXPECT_TRUE(key.extractable());
    143   EXPECT_EQ(blink::WebCryptoKeyUsageSign, key.usages());
    144   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
    145             key.algorithm().rsaHashedParams()->hash().id());
    146   EXPECT_EQ(kModulusLengthBits,
    147             key.algorithm().rsaHashedParams()->modulusLengthBits());
    148   EXPECT_BYTES_EQ_HEX(
    149       "010001",
    150       CryptoData(key.algorithm().rsaHashedParams()->publicExponent()));
    151 
    152   std::vector<uint8_t> exported_key;
    153   ASSERT_EQ(Status::Success(),
    154             ExportKey(blink::WebCryptoKeyFormatPkcs8, key, &exported_key));
    155   EXPECT_BYTES_EQ_HEX(kPrivateKeyPkcs8DerHex, exported_key);
    156 
    157   // Failing case: Empty PKCS#8 data
    158   EXPECT_EQ(Status::ErrorImportEmptyKeyData(),
    159             ImportKey(blink::WebCryptoKeyFormatPkcs8,
    160                       CryptoData(std::vector<uint8_t>()),
    161                       CreateRsaHashedImportAlgorithm(
    162                           blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
    163                           blink::WebCryptoAlgorithmIdSha1),
    164                       true,
    165                       blink::WebCryptoKeyUsageSign,
    166                       &key));
    167 
    168   // Failing case: Bad DER encoding.
    169   EXPECT_EQ(
    170       Status::DataError(),
    171       ImportKey(blink::WebCryptoKeyFormatPkcs8,
    172                 CryptoData(HexStringToBytes("618333c4cb")),
    173                 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
    174                 true,
    175                 blink::WebCryptoKeyUsageSign,
    176                 &key));
    177 
    178   // Failing case: Import RSA key but provide an inconsistent input algorithm
    179   // and usage. Several issues here:
    180   //   * AES-CBC doesn't support PKCS8 key format
    181   //   * AES-CBC doesn't support "sign" usage
    182   EXPECT_EQ(Status::ErrorUnsupportedImportKeyFormat(),
    183             ImportKey(blink::WebCryptoKeyFormatPkcs8,
    184                       CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
    185                       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
    186                       true,
    187                       blink::WebCryptoKeyUsageSign,
    188                       &key));
    189 }
    190 
    191 // Tests importing of PKCS8 data that does not define a valid RSA key.
    192 TEST(WebCryptoRsaSsaTest, ImportInvalidPkcs8) {
    193   if (!SupportsRsaPrivateKeyImport())
    194     return;
    195 
    196   // kPrivateKeyPkcs8DerHex defines an RSA private key in PKCS8 format, whose
    197   // parameters appear at the following offsets:
    198   //
    199   //   n: (offset=36, len=129)
    200   //   e: (offset=167, len=3)
    201   //   d: (offset=173, len=128)
    202   //   p: (offset=303, len=65)
    203   //   q: (offset=370, len=65)
    204   //   dp: (offset=437, len=64)
    205   //   dq; (offset=503, len=64)
    206   //   qi: (offset=569, len=64)
    207 
    208   // Do several tests, each of which invert a single byte within the input.
    209   const unsigned int kOffsetsToCorrupt[] = {
    210       50,   // inside n
    211       168,  // inside e
    212       175,  // inside d
    213       333,  // inside p
    214       373,  // inside q
    215       450,  // inside dp
    216       550,  // inside dq
    217       600,  // inside qi
    218   };
    219 
    220   for (size_t test_index = 0; test_index < arraysize(kOffsetsToCorrupt);
    221        ++test_index) {
    222     SCOPED_TRACE(test_index);
    223 
    224     unsigned int i = kOffsetsToCorrupt[test_index];
    225     std::vector<uint8_t> corrupted_data =
    226         HexStringToBytes(kPrivateKeyPkcs8DerHex);
    227     corrupted_data[i] = ~corrupted_data[i];
    228 
    229     blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
    230     EXPECT_EQ(Status::DataError(),
    231               ImportKey(blink::WebCryptoKeyFormatPkcs8,
    232                         CryptoData(corrupted_data),
    233                         CreateRsaHashedImportAlgorithm(
    234                             blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
    235                             blink::WebCryptoAlgorithmIdSha1),
    236                         true,
    237                         blink::WebCryptoKeyUsageSign,
    238                         &key));
    239   }
    240 }
    241 
    242 // Tests JWK import and export by doing a roundtrip key conversion and ensuring
    243 // it was lossless:
    244 //
    245 //   PKCS8 --> JWK --> PKCS8
    246 TEST(WebCryptoRsaSsaTest, ImportRsaPrivateKeyJwkToPkcs8RoundTrip) {
    247   if (!SupportsRsaPrivateKeyImport())
    248     return;
    249 
    250   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
    251   ASSERT_EQ(Status::Success(),
    252             ImportKey(blink::WebCryptoKeyFormatPkcs8,
    253                       CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
    254                       CreateRsaHashedImportAlgorithm(
    255                           blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
    256                           blink::WebCryptoAlgorithmIdSha1),
    257                       true,
    258                       blink::WebCryptoKeyUsageSign,
    259                       &key));
    260 
    261   std::vector<uint8_t> exported_key_jwk;
    262   ASSERT_EQ(Status::Success(),
    263             ExportKey(blink::WebCryptoKeyFormatJwk, key, &exported_key_jwk));
    264 
    265   // All of the optional parameters (p, q, dp, dq, qi) should be present in the
    266   // output.
    267   const char* expected_jwk =
    268       "{\"alg\":\"RS1\",\"d\":\"M6UEKpCyfU9UUcqbu9C0R3GhAa-IQ0Cu-YhfKku-"
    269       "kuiUpySsPFaMj5eFOtB8AmbIxqPKCSnx6PESMYhEKfxNmuVf7olqEM5wfD7X5zTkRyejlXRQ"
    270       "GlMmgxCcKrrKuig8MbS9L1PD7jfjUs7jT55QO9gMBiKtecbc7og1R8ajsyU\",\"dp\":"
    271       "\"KPoTk4ZVvh-"
    272       "KFZy6ylpy6hkMMAieGc0nSlVvNsT24Z9VSzTAd3kEJ7vdjdPt4kSDKPOF2Bsw6OQ7L_-"
    273       "gJ4YZeQ\",\"dq\":\"Gos485j6cSBJiY1_t57gp3ZoeRKZzfoJ78DlB6yyHtdDAe9b_Ui-"
    274       "RV6utuFnglWCdYCo5OjhQVHRUQqCo_LnKQ\",\"e\":\"AQAB\",\"ext\":true,\"key_"
    275       "ops\":[\"sign\"],\"kty\":\"RSA\",\"n\":"
    276       "\"pW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW_-2xYrTA8oOhKoijlN_"
    277       "1JqtykcuzB86r_OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm_4nRnxBazC0_"
    278       "DLNfKSgOE4a29kxO8i4eHyDQzoz_siSb2aITc\",\"p\":\"5-"
    279       "iUJyCod1Fyc6NWBT6iobwMlKpy1VxuhilrLfyWeUjApyy8zKfqyzVwbgmh31WhU1vZs8w0Fg"
    280       "s7bc0-2o5kQw\",\"q\":\"tp3KHPfU1-yB51uQ_MqHSrzeEj_"
    281       "ScAGAqpBHm25I3o1n7ST58Z2FuidYdPVCzSDccj5pYzZKH5QlRSsmmmeZ_Q\",\"qi\":"
    282       "\"JxVqukEm0kqB86Uoy_sn9WiG-"
    283       "ECp9uhuF6RLlP6TGVhLjiL93h5aLjvYqluo2FhBlOshkKz4MrhH8To9JKefTQ\"}";
    284 
    285   ASSERT_EQ(CryptoData(std::string(expected_jwk)),
    286             CryptoData(exported_key_jwk));
    287 
    288   ASSERT_EQ(Status::Success(),
    289             ImportKey(blink::WebCryptoKeyFormatJwk,
    290                       CryptoData(exported_key_jwk),
    291                       CreateRsaHashedImportAlgorithm(
    292                           blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
    293                           blink::WebCryptoAlgorithmIdSha1),
    294                       true,
    295                       blink::WebCryptoKeyUsageSign,
    296                       &key));
    297 
    298   std::vector<uint8_t> exported_key_pkcs8;
    299   ASSERT_EQ(
    300       Status::Success(),
    301       ExportKey(blink::WebCryptoKeyFormatPkcs8, key, &exported_key_pkcs8));
    302 
    303   ASSERT_EQ(CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
    304             CryptoData(exported_key_pkcs8));
    305 }
    306 
    307 // Tests importing multiple RSA private keys from JWK, and then exporting to
    308 // PKCS8.
    309 //
    310 // This is a regression test for http://crbug.com/378315, for which importing
    311 // a sequence of keys from JWK could yield the wrong key. The first key would
    312 // be imported correctly, however every key after that would actually import
    313 // the first key.
    314 TEST(WebCryptoRsaSsaTest, ImportMultipleRSAPrivateKeysJwk) {
    315   if (!SupportsRsaPrivateKeyImport())
    316     return;
    317 
    318   scoped_ptr<base::ListValue> key_list;
    319   ASSERT_TRUE(ReadJsonTestFileToList("rsa_private_keys.json", &key_list));
    320 
    321   // For this test to be meaningful the keys MUST be kept alive before importing
    322   // new keys.
    323   std::vector<blink::WebCryptoKey> live_keys;
    324 
    325   for (size_t key_index = 0; key_index < key_list->GetSize(); ++key_index) {
    326     SCOPED_TRACE(key_index);
    327 
    328     base::DictionaryValue* key_values;
    329     ASSERT_TRUE(key_list->GetDictionary(key_index, &key_values));
    330 
    331     // Get the JWK representation of the key.
    332     base::DictionaryValue* key_jwk;
    333     ASSERT_TRUE(key_values->GetDictionary("jwk", &key_jwk));
    334 
    335     // Get the PKCS8 representation of the key.
    336     std::string pkcs8_hex_string;
    337     ASSERT_TRUE(key_values->GetString("pkcs8", &pkcs8_hex_string));
    338     std::vector<uint8_t> pkcs8_bytes = HexStringToBytes(pkcs8_hex_string);
    339 
    340     // Get the modulus length for the key.
    341     int modulus_length_bits = 0;
    342     ASSERT_TRUE(key_values->GetInteger("modulusLength", &modulus_length_bits));
    343 
    344     blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
    345 
    346     // Import the key from JWK.
    347     ASSERT_EQ(
    348         Status::Success(),
    349         ImportKeyJwkFromDict(*key_jwk,
    350                              CreateRsaHashedImportAlgorithm(
    351                                  blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
    352                                  blink::WebCryptoAlgorithmIdSha256),
    353                              true,
    354                              blink::WebCryptoKeyUsageSign,
    355                              &private_key));
    356 
    357     live_keys.push_back(private_key);
    358 
    359     EXPECT_EQ(
    360         modulus_length_bits,
    361         static_cast<int>(
    362             private_key.algorithm().rsaHashedParams()->modulusLengthBits()));
    363 
    364     // Export to PKCS8 and verify that it matches expectation.
    365     std::vector<uint8_t> exported_key_pkcs8;
    366     ASSERT_EQ(
    367         Status::Success(),
    368         ExportKey(
    369             blink::WebCryptoKeyFormatPkcs8, private_key, &exported_key_pkcs8));
    370 
    371     EXPECT_BYTES_EQ(pkcs8_bytes, exported_key_pkcs8);
    372   }
    373 }
    374 
    375 // Import an RSA private key using JWK. Next import a JWK containing the same
    376 // modulus, but mismatched parameters for the rest. It should NOT be possible
    377 // that the second import retrieves the first key. See http://crbug.com/378315
    378 // for how that could happen.
    379 TEST(WebCryptoRsaSsaTest, ImportJwkExistingModulusAndInvalid) {
    380   if (!SupportsRsaPrivateKeyImport())
    381     return;
    382 
    383   scoped_ptr<base::ListValue> key_list;
    384   ASSERT_TRUE(ReadJsonTestFileToList("rsa_private_keys.json", &key_list));
    385 
    386   // Import a 1024-bit private key.
    387   base::DictionaryValue* key1_props;
    388   ASSERT_TRUE(key_list->GetDictionary(1, &key1_props));
    389   base::DictionaryValue* key1_jwk;
    390   ASSERT_TRUE(key1_props->GetDictionary("jwk", &key1_jwk));
    391 
    392   blink::WebCryptoKey key1 = blink::WebCryptoKey::createNull();
    393   ASSERT_EQ(Status::Success(),
    394             ImportKeyJwkFromDict(*key1_jwk,
    395                                  CreateRsaHashedImportAlgorithm(
    396                                      blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
    397                                      blink::WebCryptoAlgorithmIdSha256),
    398                                  true,
    399                                  blink::WebCryptoKeyUsageSign,
    400                                  &key1));
    401 
    402   ASSERT_EQ(1024u, key1.algorithm().rsaHashedParams()->modulusLengthBits());
    403 
    404   // Construct a JWK using the modulus of key1, but all the other fields from
    405   // another key (also a 1024-bit private key).
    406   base::DictionaryValue* key2_props;
    407   ASSERT_TRUE(key_list->GetDictionary(5, &key2_props));
    408   base::DictionaryValue* key2_jwk;
    409   ASSERT_TRUE(key2_props->GetDictionary("jwk", &key2_jwk));
    410   std::string modulus;
    411   key1_jwk->GetString("n", &modulus);
    412   key2_jwk->SetString("n", modulus);
    413 
    414   // This should fail, as the n,e,d parameters are not consistent. It MUST NOT
    415   // somehow return the key created earlier.
    416   blink::WebCryptoKey key2 = blink::WebCryptoKey::createNull();
    417   ASSERT_EQ(Status::OperationError(),
    418             ImportKeyJwkFromDict(*key2_jwk,
    419                                  CreateRsaHashedImportAlgorithm(
    420                                      blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
    421                                      blink::WebCryptoAlgorithmIdSha256),
    422                                  true,
    423                                  blink::WebCryptoKeyUsageSign,
    424                                  &key2));
    425 }
    426 
    427 // Import a JWK RSA private key with some optional parameters missing (q, dp,
    428 // dq, qi).
    429 //
    430 // The only optional parameter included is "p".
    431 //
    432 // This fails because JWA says that producers must include either ALL optional
    433 // parameters or NONE.
    434 TEST(WebCryptoRsaSsaTest, ImportRsaPrivateKeyJwkMissingOptionalParams) {
    435   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
    436 
    437   base::DictionaryValue dict;
    438   dict.SetString("kty", "RSA");
    439   dict.SetString("alg", "RS1");
    440 
    441   dict.SetString(
    442       "n",
    443       "pW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW_-2xYrTA8oOhKoijlN_"
    444       "1JqtykcuzB86r_OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm_4nRnxBazC0_"
    445       "DLNfKSgOE4a29kxO8i4eHyDQzoz_siSb2aITc");
    446   dict.SetString("e", "AQAB");
    447   dict.SetString(
    448       "d",
    449       "M6UEKpCyfU9UUcqbu9C0R3GhAa-IQ0Cu-YhfKku-"
    450       "kuiUpySsPFaMj5eFOtB8AmbIxqPKCSnx6PESMYhEKfxNmuVf7olqEM5wfD7X5zTkRyejlXRQ"
    451       "GlMmgxCcKrrKuig8MbS9L1PD7jfjUs7jT55QO9gMBiKtecbc7og1R8ajsyU");
    452 
    453   dict.SetString("p",
    454                  "5-"
    455                  "iUJyCod1Fyc6NWBT6iobwMlKpy1VxuhilrLfyWeUjApyy8zKfqyzVwbgmh31W"
    456                  "hU1vZs8w0Fgs7bc0-2o5kQw");
    457 
    458   ASSERT_EQ(Status::ErrorJwkPropertyMissing("q"),
    459             ImportKeyJwkFromDict(dict,
    460                                  CreateRsaHashedImportAlgorithm(
    461                                      blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
    462                                      blink::WebCryptoAlgorithmIdSha1),
    463                                  true,
    464                                  blink::WebCryptoKeyUsageSign,
    465                                  &key));
    466 }
    467 
    468 // Import a JWK RSA private key, without any of the optional parameters.
    469 //
    470 // According to JWA, such keys are valid, but applications SHOULD
    471 // include all the parameters when sending, and recipients MAY
    472 // accept them, but are not required to. Chromium's WebCrypto does
    473 // not allow such degenerate keys.
    474 TEST(WebCryptoRsaSsaTest, ImportRsaPrivateKeyJwkIncorrectOptionalEmpty) {
    475   if (!SupportsRsaPrivateKeyImport())
    476     return;
    477 
    478   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
    479 
    480   base::DictionaryValue dict;
    481   dict.SetString("kty", "RSA");
    482   dict.SetString("alg", "RS1");
    483 
    484   dict.SetString(
    485       "n",
    486       "pW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW_-2xYrTA8oOhKoijlN_"
    487       "1JqtykcuzB86r_OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm_4nRnxBazC0_"
    488       "DLNfKSgOE4a29kxO8i4eHyDQzoz_siSb2aITc");
    489   dict.SetString("e", "AQAB");
    490   dict.SetString(
    491       "d",
    492       "M6UEKpCyfU9UUcqbu9C0R3GhAa-IQ0Cu-YhfKku-"
    493       "kuiUpySsPFaMj5eFOtB8AmbIxqPKCSnx6PESMYhEKfxNmuVf7olqEM5wfD7X5zTkRyejlXRQ"
    494       "GlMmgxCcKrrKuig8MbS9L1PD7jfjUs7jT55QO9gMBiKtecbc7og1R8ajsyU");
    495 
    496   ASSERT_EQ(Status::ErrorJwkPropertyMissing("p"),
    497             ImportKeyJwkFromDict(dict,
    498                                  CreateRsaHashedImportAlgorithm(
    499                                      blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
    500                                      blink::WebCryptoAlgorithmIdSha1),
    501                                  true,
    502                                  blink::WebCryptoKeyUsageSign,
    503                                  &key));
    504 }
    505 
    506 // Tries importing a public RSA key whose exponent contains leading zeros.
    507 TEST(WebCryptoRsaSsaTest, ImportJwkRsaNonMinimalExponent) {
    508   base::DictionaryValue dict;
    509 
    510   dict.SetString("kty", "RSA");
    511   dict.SetString("e", "AAEAAQ");  // 00 01 00 01
    512   dict.SetString(
    513       "n",
    514       "qLOyhK-OtQs4cDSoYPFGxJGfMYdjzWxVmMiuSBGh4KvEx-CwgtaTpef87Wdc9GaFEncsDLxk"
    515       "p0LGxjD1M8jMcvYq6DPEC_JYQumEu3i9v5fAEH1VvbZi9cTg-rmEXLUUjvc5LdOq_5OuHmtm"
    516       "e7PUJHYW1PW6ENTP0ibeiNOfFvs");
    517 
    518   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
    519 
    520   EXPECT_EQ(Status::ErrorJwkBigIntegerHasLeadingZero("e"),
    521             ImportKeyJwkFromDict(dict,
    522                                  CreateRsaHashedImportAlgorithm(
    523                                      blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
    524                                      blink::WebCryptoAlgorithmIdSha256),
    525                                  false,
    526                                  blink::WebCryptoKeyUsageVerify,
    527                                  &key));
    528 }
    529 
    530 TEST(WebCryptoRsaSsaTest, GenerateKeyPairRsa) {
    531   // Note: using unrealistic short key lengths here to avoid bogging down tests.
    532 
    533   // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation (sha256)
    534   const unsigned int modulus_length = 256;
    535   const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
    536   blink::WebCryptoAlgorithm algorithm =
    537       CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
    538                                      blink::WebCryptoAlgorithmIdSha256,
    539                                      modulus_length,
    540                                      public_exponent);
    541   bool extractable = true;
    542   const blink::WebCryptoKeyUsageMask usage_mask = 0;
    543   blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
    544   blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
    545 
    546   EXPECT_EQ(Status::Success(),
    547             GenerateKeyPair(
    548                 algorithm, extractable, usage_mask, &public_key, &private_key));
    549   EXPECT_FALSE(public_key.isNull());
    550   EXPECT_FALSE(private_key.isNull());
    551   EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
    552   EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
    553   EXPECT_EQ(modulus_length,
    554             public_key.algorithm().rsaHashedParams()->modulusLengthBits());
    555   EXPECT_EQ(modulus_length,
    556             private_key.algorithm().rsaHashedParams()->modulusLengthBits());
    557   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
    558             public_key.algorithm().rsaHashedParams()->hash().id());
    559   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
    560             private_key.algorithm().rsaHashedParams()->hash().id());
    561   EXPECT_TRUE(public_key.extractable());
    562   EXPECT_EQ(extractable, private_key.extractable());
    563   EXPECT_EQ(usage_mask, public_key.usages());
    564   EXPECT_EQ(usage_mask, private_key.usages());
    565 
    566   // Try exporting the generated key pair, and then re-importing to verify that
    567   // the exported data was valid.
    568   std::vector<uint8_t> public_key_spki;
    569   EXPECT_EQ(
    570       Status::Success(),
    571       ExportKey(blink::WebCryptoKeyFormatSpki, public_key, &public_key_spki));
    572 
    573   if (SupportsRsaPrivateKeyImport()) {
    574     public_key = blink::WebCryptoKey::createNull();
    575     EXPECT_EQ(Status::Success(),
    576               ImportKey(blink::WebCryptoKeyFormatSpki,
    577                         CryptoData(public_key_spki),
    578                         CreateRsaHashedImportAlgorithm(
    579                             blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
    580                             blink::WebCryptoAlgorithmIdSha256),
    581                         true,
    582                         usage_mask,
    583                         &public_key));
    584     EXPECT_EQ(modulus_length,
    585               public_key.algorithm().rsaHashedParams()->modulusLengthBits());
    586 
    587     std::vector<uint8_t> private_key_pkcs8;
    588     EXPECT_EQ(
    589         Status::Success(),
    590         ExportKey(
    591             blink::WebCryptoKeyFormatPkcs8, private_key, &private_key_pkcs8));
    592     private_key = blink::WebCryptoKey::createNull();
    593     EXPECT_EQ(Status::Success(),
    594               ImportKey(blink::WebCryptoKeyFormatPkcs8,
    595                         CryptoData(private_key_pkcs8),
    596                         CreateRsaHashedImportAlgorithm(
    597                             blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
    598                             blink::WebCryptoAlgorithmIdSha256),
    599                         true,
    600                         usage_mask,
    601                         &private_key));
    602     EXPECT_EQ(modulus_length,
    603               private_key.algorithm().rsaHashedParams()->modulusLengthBits());
    604   }
    605 
    606   // Fail with bad modulus.
    607   algorithm =
    608       CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
    609                                      blink::WebCryptoAlgorithmIdSha256,
    610                                      0,
    611                                      public_exponent);
    612   EXPECT_EQ(Status::ErrorGenerateRsaUnsupportedModulus(),
    613             GenerateKeyPair(
    614                 algorithm, extractable, usage_mask, &public_key, &private_key));
    615 
    616   // Fail with bad exponent: larger than unsigned long.
    617   unsigned int exponent_length = sizeof(unsigned long) + 1;  // NOLINT
    618   const std::vector<uint8_t> long_exponent(exponent_length, 0x01);
    619   algorithm =
    620       CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
    621                                      blink::WebCryptoAlgorithmIdSha256,
    622                                      modulus_length,
    623                                      long_exponent);
    624   EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
    625             GenerateKeyPair(
    626                 algorithm, extractable, usage_mask, &public_key, &private_key));
    627 
    628   // Fail with bad exponent: empty.
    629   const std::vector<uint8_t> empty_exponent;
    630   algorithm =
    631       CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
    632                                      blink::WebCryptoAlgorithmIdSha256,
    633                                      modulus_length,
    634                                      empty_exponent);
    635   EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
    636             GenerateKeyPair(
    637                 algorithm, extractable, usage_mask, &public_key, &private_key));
    638 
    639   // Fail with bad exponent: all zeros.
    640   std::vector<uint8_t> exponent_with_leading_zeros(15, 0x00);
    641   algorithm =
    642       CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
    643                                      blink::WebCryptoAlgorithmIdSha256,
    644                                      modulus_length,
    645                                      exponent_with_leading_zeros);
    646   EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
    647             GenerateKeyPair(
    648                 algorithm, extractable, usage_mask, &public_key, &private_key));
    649 
    650   // Key generation success using exponent with leading zeros.
    651   exponent_with_leading_zeros.insert(exponent_with_leading_zeros.end(),
    652                                      public_exponent.begin(),
    653                                      public_exponent.end());
    654   algorithm =
    655       CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
    656                                      blink::WebCryptoAlgorithmIdSha256,
    657                                      modulus_length,
    658                                      exponent_with_leading_zeros);
    659   EXPECT_EQ(Status::Success(),
    660             GenerateKeyPair(
    661                 algorithm, extractable, usage_mask, &public_key, &private_key));
    662   EXPECT_FALSE(public_key.isNull());
    663   EXPECT_FALSE(private_key.isNull());
    664   EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
    665   EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
    666   EXPECT_TRUE(public_key.extractable());
    667   EXPECT_EQ(extractable, private_key.extractable());
    668   EXPECT_EQ(usage_mask, public_key.usages());
    669   EXPECT_EQ(usage_mask, private_key.usages());
    670 
    671   // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation (sha1)
    672   algorithm =
    673       CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
    674                                      blink::WebCryptoAlgorithmIdSha1,
    675                                      modulus_length,
    676                                      public_exponent);
    677   EXPECT_EQ(
    678       Status::Success(),
    679       GenerateKeyPair(algorithm, false, usage_mask, &public_key, &private_key));
    680   EXPECT_FALSE(public_key.isNull());
    681   EXPECT_FALSE(private_key.isNull());
    682   EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
    683   EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
    684   EXPECT_EQ(modulus_length,
    685             public_key.algorithm().rsaHashedParams()->modulusLengthBits());
    686   EXPECT_EQ(modulus_length,
    687             private_key.algorithm().rsaHashedParams()->modulusLengthBits());
    688   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
    689             public_key.algorithm().rsaHashedParams()->hash().id());
    690   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
    691             private_key.algorithm().rsaHashedParams()->hash().id());
    692   // Even though "extractable" was set to false, the public key remains
    693   // extractable.
    694   EXPECT_TRUE(public_key.extractable());
    695   EXPECT_FALSE(private_key.extractable());
    696   EXPECT_EQ(usage_mask, public_key.usages());
    697   EXPECT_EQ(usage_mask, private_key.usages());
    698 
    699   // Exporting a private key as SPKI format doesn't make sense. However this
    700   // will first fail because the key is not extractable.
    701   std::vector<uint8_t> output;
    702   EXPECT_EQ(Status::ErrorKeyNotExtractable(),
    703             ExportKey(blink::WebCryptoKeyFormatSpki, private_key, &output));
    704 
    705   // Re-generate an extractable private_key and try to export it as SPKI format.
    706   // This should fail since spki is for public keys.
    707   EXPECT_EQ(
    708       Status::Success(),
    709       GenerateKeyPair(algorithm, true, usage_mask, &public_key, &private_key));
    710   EXPECT_EQ(Status::ErrorUnexpectedKeyType(),
    711             ExportKey(blink::WebCryptoKeyFormatSpki, private_key, &output));
    712 }
    713 
    714 TEST(WebCryptoRsaSsaTest, GenerateKeyPairRsaBadModulusLength) {
    715   const unsigned int kBadModulusBits[] = {
    716       0,
    717       248,         // Too small.
    718       257,         // Not a multiple of 8.
    719       1023,        // Not a multiple of 8.
    720       0xFFFFFFFF,  // Too big.
    721       16384 + 8,   // 16384 is the maxmimum length that NSS succeeds for.
    722   };
    723 
    724   const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
    725 
    726   for (size_t i = 0; i < arraysize(kBadModulusBits); ++i) {
    727     const unsigned int modulus_length_bits = kBadModulusBits[i];
    728     blink::WebCryptoAlgorithm algorithm = CreateRsaHashedKeyGenAlgorithm(
    729         blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
    730         blink::WebCryptoAlgorithmIdSha256,
    731         modulus_length_bits,
    732         public_exponent);
    733     bool extractable = true;
    734     const blink::WebCryptoKeyUsageMask usage_mask = 0;
    735     blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
    736     blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
    737 
    738     EXPECT_EQ(
    739         Status::ErrorGenerateRsaUnsupportedModulus(),
    740         GenerateKeyPair(
    741             algorithm, extractable, usage_mask, &public_key, &private_key));
    742   }
    743 }
    744 
    745 // Try generating RSA key pairs using unsupported public exponents. Only
    746 // exponents of 3 and 65537 are supported. While both OpenSSL and NSS can
    747 // support other values, OpenSSL hangs when given invalid exponents, so use a
    748 // whitelist to validate the parameters.
    749 TEST(WebCryptoRsaSsaTest, GenerateKeyPairRsaBadExponent) {
    750   const unsigned int modulus_length = 1024;
    751 
    752   const char* const kPublicExponents[] = {
    753       "11",  // 17 - This is a valid public exponent, but currently disallowed.
    754       "00",     "01", "02",
    755       "010000",  // 65536
    756   };
    757 
    758   for (size_t i = 0; i < arraysize(kPublicExponents); ++i) {
    759     SCOPED_TRACE(i);
    760     blink::WebCryptoAlgorithm algorithm = CreateRsaHashedKeyGenAlgorithm(
    761         blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
    762         blink::WebCryptoAlgorithmIdSha256,
    763         modulus_length,
    764         HexStringToBytes(kPublicExponents[i]));
    765 
    766     blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
    767     blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
    768 
    769     EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
    770               GenerateKeyPair(algorithm, true, 0, &public_key, &private_key));
    771   }
    772 }
    773 
    774 TEST(WebCryptoRsaSsaTest, SignVerifyFailures) {
    775   if (!SupportsRsaPrivateKeyImport())
    776     return;
    777 
    778   // Import a key pair.
    779   blink::WebCryptoAlgorithm import_algorithm =
    780       CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
    781                                      blink::WebCryptoAlgorithmIdSha1);
    782   blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
    783   blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
    784   ASSERT_NO_FATAL_FAILURE(
    785       ImportRsaKeyPair(HexStringToBytes(kPublicKeySpkiDerHex),
    786                        HexStringToBytes(kPrivateKeyPkcs8DerHex),
    787                        import_algorithm,
    788                        false,
    789                        blink::WebCryptoKeyUsageVerify,
    790                        blink::WebCryptoKeyUsageSign,
    791                        &public_key,
    792                        &private_key));
    793 
    794   blink::WebCryptoAlgorithm algorithm =
    795       CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5);
    796 
    797   std::vector<uint8_t> signature;
    798   bool signature_match;
    799 
    800   // Compute a signature.
    801   const std::vector<uint8_t> data = HexStringToBytes("010203040506070809");
    802   ASSERT_EQ(Status::Success(),
    803             Sign(algorithm, private_key, CryptoData(data), &signature));
    804 
    805   // Ensure truncated signature does not verify by passing one less byte.
    806   EXPECT_EQ(
    807       Status::Success(),
    808       Verify(algorithm,
    809              public_key,
    810              CryptoData(vector_as_array(&signature), signature.size() - 1),
    811              CryptoData(data),
    812              &signature_match));
    813   EXPECT_FALSE(signature_match);
    814 
    815   // Ensure truncated signature does not verify by passing no bytes.
    816   EXPECT_EQ(Status::Success(),
    817             Verify(algorithm,
    818                    public_key,
    819                    CryptoData(),
    820                    CryptoData(data),
    821                    &signature_match));
    822   EXPECT_FALSE(signature_match);
    823 
    824   // Ensure corrupted signature does not verify.
    825   std::vector<uint8_t> corrupt_sig = signature;
    826   corrupt_sig[corrupt_sig.size() / 2] ^= 0x1;
    827   EXPECT_EQ(Status::Success(),
    828             Verify(algorithm,
    829                    public_key,
    830                    CryptoData(corrupt_sig),
    831                    CryptoData(data),
    832                    &signature_match));
    833   EXPECT_FALSE(signature_match);
    834 
    835   // Ensure signatures that are greater than the modulus size fail.
    836   const unsigned int long_message_size_bytes = 1024;
    837   DCHECK_GT(long_message_size_bytes, kModulusLengthBits / 8);
    838   const unsigned char kLongSignature[long_message_size_bytes] = {0};
    839   EXPECT_EQ(Status::Success(),
    840             Verify(algorithm,
    841                    public_key,
    842                    CryptoData(kLongSignature, sizeof(kLongSignature)),
    843                    CryptoData(data),
    844                    &signature_match));
    845   EXPECT_FALSE(signature_match);
    846 
    847   // Ensure that signing and verifying with an incompatible algorithm fails.
    848   algorithm = CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep);
    849 
    850   EXPECT_EQ(Status::ErrorUnexpected(),
    851             Sign(algorithm, private_key, CryptoData(data), &signature));
    852   EXPECT_EQ(Status::ErrorUnexpected(),
    853             Verify(algorithm,
    854                    public_key,
    855                    CryptoData(signature),
    856                    CryptoData(data),
    857                    &signature_match));
    858 
    859   // Some crypto libraries (NSS) can automatically select the RSA SSA inner hash
    860   // based solely on the contents of the input signature data. In the Web Crypto
    861   // implementation, the inner hash should be specified uniquely by the key
    862   // algorithm parameter. To validate this behavior, call Verify with a computed
    863   // signature that used one hash type (SHA-1), but pass in a key with a
    864   // different inner hash type (SHA-256). If the hash type is determined by the
    865   // signature itself (undesired), the verify will pass, while if the hash type
    866   // is specified by the key algorithm (desired), the verify will fail.
    867 
    868   // Compute a signature using SHA-1 as the inner hash.
    869   EXPECT_EQ(Status::Success(),
    870             Sign(CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
    871                  private_key,
    872                  CryptoData(data),
    873                  &signature));
    874 
    875   blink::WebCryptoKey public_key_256 = blink::WebCryptoKey::createNull();
    876   EXPECT_EQ(Status::Success(),
    877             ImportKey(blink::WebCryptoKeyFormatSpki,
    878                       CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
    879                       CreateRsaHashedImportAlgorithm(
    880                           blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
    881                           blink::WebCryptoAlgorithmIdSha256),
    882                       true,
    883                       blink::WebCryptoKeyUsageVerify,
    884                       &public_key_256));
    885 
    886   // Now verify using an algorithm whose inner hash is SHA-256, not SHA-1. The
    887   // signature should not verify.
    888   // NOTE: public_key was produced by generateKey, and so its associated
    889   // algorithm has WebCryptoRsaKeyGenParams and not WebCryptoRsaSsaParams. Thus
    890   // it has no inner hash to conflict with the input algorithm.
    891   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
    892             private_key.algorithm().rsaHashedParams()->hash().id());
    893   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
    894             public_key_256.algorithm().rsaHashedParams()->hash().id());
    895 
    896   bool is_match;
    897   EXPECT_EQ(Status::Success(),
    898             Verify(CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
    899                    public_key_256,
    900                    CryptoData(signature),
    901                    CryptoData(data),
    902                    &is_match));
    903   EXPECT_FALSE(is_match);
    904 }
    905 
    906 TEST(WebCryptoRsaSsaTest, SignVerifyKnownAnswer) {
    907   if (!SupportsRsaPrivateKeyImport())
    908     return;
    909 
    910   scoped_ptr<base::ListValue> tests;
    911   ASSERT_TRUE(ReadJsonTestFileToList("pkcs1v15_sign.json", &tests));
    912 
    913   // Import the key pair.
    914   blink::WebCryptoAlgorithm import_algorithm =
    915       CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
    916                                      blink::WebCryptoAlgorithmIdSha1);
    917   blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
    918   blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
    919   ASSERT_NO_FATAL_FAILURE(
    920       ImportRsaKeyPair(HexStringToBytes(kPublicKeySpkiDerHex),
    921                        HexStringToBytes(kPrivateKeyPkcs8DerHex),
    922                        import_algorithm,
    923                        false,
    924                        blink::WebCryptoKeyUsageVerify,
    925                        blink::WebCryptoKeyUsageSign,
    926                        &public_key,
    927                        &private_key));
    928 
    929   blink::WebCryptoAlgorithm algorithm =
    930       CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5);
    931 
    932   // Validate the signatures are computed and verified as expected.
    933   std::vector<uint8_t> signature;
    934   for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
    935     SCOPED_TRACE(test_index);
    936 
    937     base::DictionaryValue* test;
    938     ASSERT_TRUE(tests->GetDictionary(test_index, &test));
    939 
    940     std::vector<uint8_t> test_message =
    941         GetBytesFromHexString(test, "message_hex");
    942     std::vector<uint8_t> test_signature =
    943         GetBytesFromHexString(test, "signature_hex");
    944 
    945     signature.clear();
    946     ASSERT_EQ(
    947         Status::Success(),
    948         Sign(algorithm, private_key, CryptoData(test_message), &signature));
    949     EXPECT_BYTES_EQ(test_signature, signature);
    950 
    951     bool is_match = false;
    952     ASSERT_EQ(Status::Success(),
    953               Verify(algorithm,
    954                      public_key,
    955                      CryptoData(test_signature),
    956                      CryptoData(test_message),
    957                      &is_match));
    958     EXPECT_TRUE(is_match);
    959   }
    960 }
    961 
    962 // Try importing an RSA-SSA public key with unsupported key usages using SPKI
    963 // format. RSA-SSA public keys only support the 'verify' usage.
    964 TEST(WebCryptoRsaSsaTest, ImportRsaSsaPublicKeyBadUsage_SPKI) {
    965   const blink::WebCryptoAlgorithm algorithm =
    966       CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
    967                                      blink::WebCryptoAlgorithmIdSha256);
    968 
    969   blink::WebCryptoKeyUsageMask bad_usages[] = {
    970       blink::WebCryptoKeyUsageSign,
    971       blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
    972       blink::WebCryptoKeyUsageEncrypt,
    973       blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
    974   };
    975 
    976   for (size_t i = 0; i < arraysize(bad_usages); ++i) {
    977     SCOPED_TRACE(i);
    978 
    979     blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
    980     ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
    981               ImportKey(blink::WebCryptoKeyFormatSpki,
    982                         CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
    983                         algorithm,
    984                         false,
    985                         bad_usages[i],
    986                         &public_key));
    987   }
    988 }
    989 
    990 // Try importing an RSA-SSA public key with unsupported key usages using JWK
    991 // format. RSA-SSA public keys only support the 'verify' usage.
    992 TEST(WebCryptoRsaSsaTest, ImportRsaSsaPublicKeyBadUsage_JWK) {
    993   const blink::WebCryptoAlgorithm algorithm =
    994       CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
    995                                      blink::WebCryptoAlgorithmIdSha256);
    996 
    997   blink::WebCryptoKeyUsageMask bad_usages[] = {
    998       blink::WebCryptoKeyUsageSign,
    999       blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
   1000       blink::WebCryptoKeyUsageEncrypt,
   1001       blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
   1002   };
   1003 
   1004   base::DictionaryValue dict;
   1005   RestoreJwkRsaDictionary(&dict);
   1006   dict.Remove("use", NULL);
   1007   dict.SetString("alg", "RS256");
   1008 
   1009   for (size_t i = 0; i < arraysize(bad_usages); ++i) {
   1010     SCOPED_TRACE(i);
   1011 
   1012     blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
   1013     ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
   1014               ImportKeyJwkFromDict(
   1015                   dict, algorithm, false, bad_usages[i], &public_key));
   1016   }
   1017 }
   1018 
   1019 // Generate an RSA-SSA key pair with invalid usages. RSA-SSA supports:
   1020 //   'sign', 'verify'
   1021 TEST(WebCryptoRsaSsaTest, GenerateKeyBadUsages) {
   1022   blink::WebCryptoKeyUsageMask bad_usages[] = {
   1023       blink::WebCryptoKeyUsageDecrypt,
   1024       blink::WebCryptoKeyUsageVerify | blink::WebCryptoKeyUsageDecrypt,
   1025       blink::WebCryptoKeyUsageWrapKey,
   1026   };
   1027 
   1028   const unsigned int modulus_length = 256;
   1029   const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
   1030 
   1031   for (size_t i = 0; i < arraysize(bad_usages); ++i) {
   1032     SCOPED_TRACE(i);
   1033 
   1034     blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
   1035     blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
   1036 
   1037     ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
   1038               GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
   1039                                   blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
   1040                                   blink::WebCryptoAlgorithmIdSha256,
   1041                                   modulus_length,
   1042                                   public_exponent),
   1043                               true,
   1044                               bad_usages[i],
   1045                               &public_key,
   1046                               &private_key));
   1047   }
   1048 }
   1049 
   1050 // Generate an RSA-SSA key pair. The public and private keys should select the
   1051 // key usages which are applicable, and not have the exact same usages as was
   1052 // specified to GenerateKey
   1053 TEST(WebCryptoRsaSsaTest, GenerateKeyPairIntersectUsages) {
   1054   const unsigned int modulus_length = 256;
   1055   const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
   1056 
   1057   blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
   1058   blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
   1059 
   1060   ASSERT_EQ(Status::Success(),
   1061             GenerateKeyPair(
   1062                 CreateRsaHashedKeyGenAlgorithm(
   1063                     blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
   1064                     blink::WebCryptoAlgorithmIdSha256,
   1065                     modulus_length,
   1066                     public_exponent),
   1067                 true,
   1068                 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
   1069                 &public_key,
   1070                 &private_key));
   1071 
   1072   EXPECT_EQ(blink::WebCryptoKeyUsageVerify, public_key.usages());
   1073   EXPECT_EQ(blink::WebCryptoKeyUsageSign, private_key.usages());
   1074 
   1075   // Try again but this time without the Verify usages.
   1076   ASSERT_EQ(Status::Success(),
   1077             GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
   1078                                 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
   1079                                 blink::WebCryptoAlgorithmIdSha256,
   1080                                 modulus_length,
   1081                                 public_exponent),
   1082                             true,
   1083                             blink::WebCryptoKeyUsageSign,
   1084                             &public_key,
   1085                             &private_key));
   1086 
   1087   EXPECT_EQ(0, public_key.usages());
   1088   EXPECT_EQ(blink::WebCryptoKeyUsageSign, private_key.usages());
   1089 }
   1090 
   1091 TEST(WebCryptoRsaSsaTest, ImportExportJwkRsaPublicKey) {
   1092   struct TestCase {
   1093     const blink::WebCryptoAlgorithmId hash;
   1094     const blink::WebCryptoKeyUsageMask usage;
   1095     const char* const jwk_alg;
   1096   };
   1097   const TestCase kTests[] = {
   1098       {blink::WebCryptoAlgorithmIdSha1, blink::WebCryptoKeyUsageVerify, "RS1"},
   1099       {blink::WebCryptoAlgorithmIdSha256, blink::WebCryptoKeyUsageVerify,
   1100        "RS256"},
   1101       {blink::WebCryptoAlgorithmIdSha384, blink::WebCryptoKeyUsageVerify,
   1102        "RS384"},
   1103       {blink::WebCryptoAlgorithmIdSha512, blink::WebCryptoKeyUsageVerify,
   1104        "RS512"}};
   1105 
   1106   for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(kTests);
   1107        ++test_index) {
   1108     SCOPED_TRACE(test_index);
   1109     const TestCase& test = kTests[test_index];
   1110 
   1111     const blink::WebCryptoAlgorithm import_algorithm =
   1112         CreateRsaHashedImportAlgorithm(
   1113             blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, test.hash);
   1114 
   1115     // Import the spki to create a public key
   1116     blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
   1117     ASSERT_EQ(Status::Success(),
   1118               ImportKey(blink::WebCryptoKeyFormatSpki,
   1119                         CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
   1120                         import_algorithm,
   1121                         true,
   1122                         test.usage,
   1123                         &public_key));
   1124 
   1125     // Export the public key as JWK and verify its contents
   1126     std::vector<uint8_t> jwk;
   1127     ASSERT_EQ(Status::Success(),
   1128               ExportKey(blink::WebCryptoKeyFormatJwk, public_key, &jwk));
   1129     EXPECT_TRUE(VerifyPublicJwk(jwk,
   1130                                 test.jwk_alg,
   1131                                 kPublicKeyModulusHex,
   1132                                 kPublicKeyExponentHex,
   1133                                 test.usage));
   1134 
   1135     // Import the JWK back in to create a new key
   1136     blink::WebCryptoKey public_key2 = blink::WebCryptoKey::createNull();
   1137     ASSERT_EQ(Status::Success(),
   1138               ImportKey(blink::WebCryptoKeyFormatJwk,
   1139                         CryptoData(jwk),
   1140                         import_algorithm,
   1141                         true,
   1142                         test.usage,
   1143                         &public_key2));
   1144     ASSERT_TRUE(public_key2.handle());
   1145     EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key2.type());
   1146     EXPECT_TRUE(public_key2.extractable());
   1147     EXPECT_EQ(import_algorithm.id(), public_key2.algorithm().id());
   1148 
   1149     // Export the new key as spki and compare to the original.
   1150     std::vector<uint8_t> spki;
   1151     ASSERT_EQ(Status::Success(),
   1152               ExportKey(blink::WebCryptoKeyFormatSpki, public_key2, &spki));
   1153     EXPECT_BYTES_EQ_HEX(kPublicKeySpkiDerHex, CryptoData(spki));
   1154   }
   1155 }
   1156 
   1157 TEST(WebCryptoRsaSsaTest, ImportJwkRsaFailures) {
   1158   base::DictionaryValue dict;
   1159   RestoreJwkRsaDictionary(&dict);
   1160   blink::WebCryptoAlgorithm algorithm =
   1161       CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
   1162                                      blink::WebCryptoAlgorithmIdSha256);
   1163   blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageVerify;
   1164   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
   1165 
   1166   // An RSA public key JWK _must_ have an "n" (modulus) and an "e" (exponent)
   1167   // entry, while an RSA private key must have those plus at least a "d"
   1168   // (private exponent) entry.
   1169   // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18,
   1170   // section 6.3.
   1171 
   1172   // Baseline pass.
   1173   EXPECT_EQ(Status::Success(),
   1174             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
   1175   EXPECT_EQ(algorithm.id(), key.algorithm().id());
   1176   EXPECT_FALSE(key.extractable());
   1177   EXPECT_EQ(blink::WebCryptoKeyUsageVerify, key.usages());
   1178   EXPECT_EQ(blink::WebCryptoKeyTypePublic, key.type());
   1179 
   1180   // The following are specific failure cases for when kty = "RSA".
   1181 
   1182   // Fail if either "n" or "e" is not present or malformed.
   1183   const std::string kKtyParmName[] = {"n", "e"};
   1184   for (size_t idx = 0; idx < ARRAYSIZE_UNSAFE(kKtyParmName); ++idx) {
   1185     // Fail on missing parameter.
   1186     dict.Remove(kKtyParmName[idx], NULL);
   1187     EXPECT_NE(Status::Success(),
   1188               ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
   1189     RestoreJwkRsaDictionary(&dict);
   1190 
   1191     // Fail on bad b64 parameter encoding.
   1192     dict.SetString(kKtyParmName[idx], "Qk3f0DsytU8lfza2au #$% Htaw2xpop9yTuH0");
   1193     EXPECT_NE(Status::Success(),
   1194               ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
   1195     RestoreJwkRsaDictionary(&dict);
   1196 
   1197     // Fail on empty parameter.
   1198     dict.SetString(kKtyParmName[idx], "");
   1199     EXPECT_EQ(Status::ErrorJwkEmptyBigInteger(kKtyParmName[idx]),
   1200               ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
   1201     RestoreJwkRsaDictionary(&dict);
   1202   }
   1203 }
   1204 
   1205 }  // namespace
   1206 
   1207 }  // namespace webcrypto
   1208 
   1209 }  // namespace content
   1210