1/*
2 * Copyright (C) 2013 Apple 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
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "CryptoAlgorithmAES_KW.h"
28
29#if ENABLE(WEB_CRYPTO)
30
31#include "CryptoAlgorithmAesKeyParams.h"
32#include "CryptoKeyAES.h"
33#include <wtf/Variant.h>
34
35namespace WebCore {
36
37namespace CryptoAlgorithmAES_KWInternal {
38static const char* const ALG128 = "A128KW";
39static const char* const ALG192 = "A192KW";
40static const char* const ALG256 = "A256KW";
41}
42
43static inline bool usagesAreInvalidForCryptoAlgorithmAES_KW(CryptoKeyUsageBitmap usages)
44{
45 return usages & (CryptoKeyUsageSign | CryptoKeyUsageVerify | CryptoKeyUsageDeriveKey | CryptoKeyUsageDeriveBits | CryptoKeyUsageEncrypt | CryptoKeyUsageDecrypt);
46}
47
48Ref<CryptoAlgorithm> CryptoAlgorithmAES_KW::create()
49{
50 return adoptRef(*new CryptoAlgorithmAES_KW);
51}
52
53CryptoAlgorithmIdentifier CryptoAlgorithmAES_KW::identifier() const
54{
55 return s_identifier;
56}
57
58void CryptoAlgorithmAES_KW::generateKey(const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyOrKeyPairCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext&)
59{
60 if (usagesAreInvalidForCryptoAlgorithmAES_KW(usages)) {
61 exceptionCallback(SyntaxError);
62 return;
63 }
64
65 auto result = CryptoKeyAES::generate(CryptoAlgorithmIdentifier::AES_KW, downcast<CryptoAlgorithmAesKeyParams>(parameters).length, extractable, usages);
66 if (!result) {
67 exceptionCallback(OperationError);
68 return;
69 }
70
71 callback(WTFMove(result));
72}
73
74void CryptoAlgorithmAES_KW::importKey(CryptoKeyFormat format, KeyData&& data, const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyCallback&& callback, ExceptionCallback&& exceptionCallback)
75{
76 using namespace CryptoAlgorithmAES_KWInternal;
77
78 if (usagesAreInvalidForCryptoAlgorithmAES_KW(usages)) {
79 exceptionCallback(SyntaxError);
80 return;
81 }
82
83 RefPtr<CryptoKeyAES> result;
84 switch (format) {
85 case CryptoKeyFormat::Raw:
86 result = CryptoKeyAES::importRaw(parameters.identifier, WTFMove(WTF::get<Vector<uint8_t>>(data)), extractable, usages);
87 break;
88 case CryptoKeyFormat::Jwk: {
89 result = CryptoKeyAES::importJwk(parameters.identifier, WTFMove(WTF::get<JsonWebKey>(data)), extractable, usages, [](size_t length, const String& alg) -> bool {
90 switch (length) {
91 case CryptoKeyAES::s_length128:
92 return alg.isNull() || alg == ALG128;
93 case CryptoKeyAES::s_length192:
94 return alg.isNull() || alg == ALG192;
95 case CryptoKeyAES::s_length256:
96 return alg.isNull() || alg == ALG256;
97 }
98 return false;
99 });
100 break;
101 }
102 default:
103 exceptionCallback(NotSupportedError);
104 return;
105 }
106 if (!result) {
107 exceptionCallback(DataError);
108 return;
109 }
110
111 callback(*result);
112}
113
114void CryptoAlgorithmAES_KW::exportKey(CryptoKeyFormat format, Ref<CryptoKey>&& key, KeyDataCallback&& callback, ExceptionCallback&& exceptionCallback)
115{
116 using namespace CryptoAlgorithmAES_KWInternal;
117 const auto& aesKey = downcast<CryptoKeyAES>(key.get());
118
119 if (aesKey.key().isEmpty()) {
120 exceptionCallback(OperationError);
121 return;
122 }
123
124 KeyData result;
125 switch (format) {
126 case CryptoKeyFormat::Raw:
127 result = Vector<uint8_t>(aesKey.key());
128 break;
129 case CryptoKeyFormat::Jwk: {
130 JsonWebKey jwk = aesKey.exportJwk();
131 switch (aesKey.key().size() * 8) {
132 case CryptoKeyAES::s_length128:
133 jwk.alg = String(ALG128);
134 break;
135 case CryptoKeyAES::s_length192:
136 jwk.alg = String(ALG192);
137 break;
138 case CryptoKeyAES::s_length256:
139 jwk.alg = String(ALG256);
140 break;
141 default:
142 ASSERT_NOT_REACHED();
143 }
144 result = WTFMove(jwk);
145 break;
146 }
147 default:
148 exceptionCallback(NotSupportedError);
149 return;
150 }
151
152 callback(format, WTFMove(result));
153}
154
155void CryptoAlgorithmAES_KW::wrapKey(Ref<CryptoKey>&& key, Vector<uint8_t>&& data, VectorCallback&& callback, ExceptionCallback&& exceptionCallback)
156{
157 if (data.size() % 8) {
158 exceptionCallback(OperationError);
159 return;
160 }
161
162 auto result = platformWrapKey(downcast<CryptoKeyAES>(key.get()), WTFMove(data));
163 if (result.hasException()) {
164 exceptionCallback(result.releaseException().code());
165 return;
166 }
167
168 callback(result.releaseReturnValue());
169}
170
171void CryptoAlgorithmAES_KW::unwrapKey(Ref<CryptoKey>&& key, Vector<uint8_t>&& data, VectorCallback&& callback, ExceptionCallback&& exceptionCallback)
172{
173 auto result = platformUnwrapKey(downcast<CryptoKeyAES>(key.get()), WTFMove(data));
174 if (result.hasException()) {
175 exceptionCallback(result.releaseException().code());
176 return;
177 }
178
179 callback(result.releaseReturnValue());
180}
181
182ExceptionOr<size_t> CryptoAlgorithmAES_KW::getKeyLength(const CryptoAlgorithmParameters& parameters)
183{
184 return CryptoKeyAES::getKeyLength(parameters);
185}
186
187}
188
189#endif // ENABLE(WEB_CRYPTO)
190