[WebCrypto] Crypto operations should copy their parameters before hoping to another...
[WebKit-https.git] / Source / WebCore / crypto / algorithms / CryptoAlgorithmAES_KW.cpp
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(SUBTLE_CRYPTO)
30
31 #include "CryptoAlgorithmAesKeyParams.h"
32 #include "CryptoKeyAES.h"
33 #include <wtf/Variant.h>
34
35 namespace WebCore {
36
37 namespace CryptoAlgorithmAES_KWInternal {
38 static const char* const ALG128 = "A128KW";
39 static const char* const ALG192 = "A192KW";
40 static const char* const ALG256 = "A256KW";
41 }
42
43 static inline bool usagesAreInvalidForCryptoAlgorithmAES_KW(CryptoKeyUsageBitmap usages)
44 {
45     return usages & (CryptoKeyUsageSign | CryptoKeyUsageVerify | CryptoKeyUsageDeriveKey | CryptoKeyUsageDeriveBits | CryptoKeyUsageEncrypt | CryptoKeyUsageDecrypt);
46 }
47
48 Ref<CryptoAlgorithm> CryptoAlgorithmAES_KW::create()
49 {
50     return adoptRef(*new CryptoAlgorithmAES_KW);
51 }
52
53 CryptoAlgorithmIdentifier CryptoAlgorithmAES_KW::identifier() const
54 {
55     return s_identifier;
56 }
57
58 void 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
74 void 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
114 void 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
155 void 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
171 void 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
182 ExceptionOr<size_t> CryptoAlgorithmAES_KW::getKeyLength(const CryptoAlgorithmParameters& parameters)
183 {
184     return CryptoKeyAES::getKeyLength(parameters);
185 }
186
187 }
188
189 #endif // ENABLE(SUBTLE_CRYPTO)