Home | History | Annotate | Download | only in webcrypto
      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 "content/child/webcrypto/structured_clone.h"
      6 
      7 #include "base/logging.h"
      8 #include "content/child/webcrypto/algorithm_dispatch.h"
      9 #include "content/child/webcrypto/platform_crypto.h"
     10 #include "content/child/webcrypto/status.h"
     11 #include "content/child/webcrypto/webcrypto_util.h"
     12 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
     13 
     14 namespace content {
     15 
     16 namespace webcrypto {
     17 
     18 namespace {
     19 
     20 // Returns the key format to use for structured cloning.
     21 blink::WebCryptoKeyFormat GetCloneFormatForKeyType(
     22     blink::WebCryptoKeyType type) {
     23   switch (type) {
     24     case blink::WebCryptoKeyTypeSecret:
     25       return blink::WebCryptoKeyFormatRaw;
     26     case blink::WebCryptoKeyTypePublic:
     27       return blink::WebCryptoKeyFormatSpki;
     28     case blink::WebCryptoKeyTypePrivate:
     29       return blink::WebCryptoKeyFormatPkcs8;
     30   }
     31 
     32   NOTREACHED();
     33   return blink::WebCryptoKeyFormatRaw;
     34 }
     35 
     36 // Converts a KeyAlgorithm into an equivalent Algorithm for import.
     37 blink::WebCryptoAlgorithm KeyAlgorithmToImportAlgorithm(
     38     const blink::WebCryptoKeyAlgorithm& algorithm) {
     39   switch (algorithm.paramsType()) {
     40     case blink::WebCryptoKeyAlgorithmParamsTypeAes:
     41       return CreateAlgorithm(algorithm.id());
     42     case blink::WebCryptoKeyAlgorithmParamsTypeHmac:
     43       return CreateHmacImportAlgorithm(algorithm.hmacParams()->hash().id());
     44     case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed:
     45       return CreateRsaHashedImportAlgorithm(
     46           algorithm.id(), algorithm.rsaHashedParams()->hash().id());
     47     case blink::WebCryptoKeyAlgorithmParamsTypeNone:
     48       break;
     49     default:
     50       break;
     51   }
     52   return blink::WebCryptoAlgorithm::createNull();
     53 }
     54 
     55 // There is some duplicated information in the serialized format used by
     56 // structured clone (since the KeyAlgorithm is serialized separately from the
     57 // key data). Use this extra information to further validate what was
     58 // deserialized from the key data.
     59 //
     60 // A failure here implies either a bug in the code, or that the serialized data
     61 // was corrupted.
     62 bool ValidateDeserializedKey(const blink::WebCryptoKey& key,
     63                              const blink::WebCryptoKeyAlgorithm& algorithm,
     64                              blink::WebCryptoKeyType type) {
     65   if (algorithm.id() != key.algorithm().id())
     66     return false;
     67 
     68   if (key.type() != type)
     69     return false;
     70 
     71   switch (algorithm.paramsType()) {
     72     case blink::WebCryptoKeyAlgorithmParamsTypeAes:
     73       if (algorithm.aesParams()->lengthBits() !=
     74           key.algorithm().aesParams()->lengthBits())
     75         return false;
     76       break;
     77     case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed:
     78       if (algorithm.rsaHashedParams()->modulusLengthBits() !=
     79           key.algorithm().rsaHashedParams()->modulusLengthBits())
     80         return false;
     81       if (algorithm.rsaHashedParams()->publicExponent().size() !=
     82           key.algorithm().rsaHashedParams()->publicExponent().size())
     83         return false;
     84       if (memcmp(algorithm.rsaHashedParams()->publicExponent().data(),
     85                  key.algorithm().rsaHashedParams()->publicExponent().data(),
     86                  key.algorithm().rsaHashedParams()->publicExponent().size()) !=
     87           0)
     88         return false;
     89       break;
     90     case blink::WebCryptoKeyAlgorithmParamsTypeNone:
     91     case blink::WebCryptoKeyAlgorithmParamsTypeHmac:
     92       break;
     93     default:
     94       return false;
     95   }
     96 
     97   return true;
     98 }
     99 
    100 }  // namespace
    101 
    102 // Note that this function is called from the target Blink thread.
    103 bool SerializeKeyForClone(const blink::WebCryptoKey& key,
    104                           blink::WebVector<uint8_t>* key_data) {
    105   return PlatformSerializeKeyForClone(key, key_data);
    106 }
    107 
    108 // Note that this function is called from the target Blink thread.
    109 bool DeserializeKeyForClone(const blink::WebCryptoKeyAlgorithm& algorithm,
    110                             blink::WebCryptoKeyType type,
    111                             bool extractable,
    112                             blink::WebCryptoKeyUsageMask usage_mask,
    113                             const CryptoData& key_data,
    114                             blink::WebCryptoKey* key) {
    115   // TODO(eroman): This should not call into the platform crypto layer.
    116   // Otherwise it runs the risk of stalling while the NSS/OpenSSL global locks
    117   // are held.
    118   //
    119   // An alternate approach is to defer the key import until the key is used.
    120   // However this means that any deserialization errors would have to be
    121   // surfaced as WebCrypto errors, leading to slightly different behaviors. For
    122   // instance you could clone a key which fails to be deserialized.
    123   Status status = ImportKey(GetCloneFormatForKeyType(type),
    124                             key_data,
    125                             KeyAlgorithmToImportAlgorithm(algorithm),
    126                             extractable,
    127                             usage_mask,
    128                             key);
    129   if (status.IsError())
    130     return false;
    131   return ValidateDeserializedKey(*key, algorithm, type);
    132 }
    133 
    134 }  // namespace webcrypto
    135 
    136 }  // namespace content
    137