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