0b96c87ad30250ce15a5e8909ed98bf0c5c50ff3
[WebKit-https.git] / Source / WebCore / crypto / algorithms / CryptoAlgorithmAES_CBC.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_CBC.h"
28
29 #if ENABLE(SUBTLE_CRYPTO)
30
31 #include "CryptoAlgorithmAesCbcParamsDeprecated.h"
32 #include "CryptoAlgorithmAesKeyGenParams.h"
33 #include "CryptoAlgorithmAesKeyGenParamsDeprecated.h"
34 #include "CryptoKeyAES.h"
35 #include "CryptoKeyDataOctetSequence.h"
36 #include "ExceptionCode.h"
37
38 namespace WebCore {
39
40 static const char* const ALG128 = "A128CBC";
41 static const char* const ALG192 = "A192CBC";
42 static const char* const ALG256 = "A256CBC";
43
44 static inline bool usagesAreInvalidForCryptoAlgorithmAES_CBC(CryptoKeyUsageBitmap usages)
45 {
46     return usages & (CryptoKeyUsageSign | CryptoKeyUsageVerify | CryptoKeyUsageDeriveKey | CryptoKeyUsageDeriveBits);
47 }
48
49 Ref<CryptoAlgorithm> CryptoAlgorithmAES_CBC::create()
50 {
51     return adoptRef(*new CryptoAlgorithmAES_CBC);
52 }
53
54 CryptoAlgorithmIdentifier CryptoAlgorithmAES_CBC::identifier() const
55 {
56     return s_identifier;
57 }
58
59 bool CryptoAlgorithmAES_CBC::keyAlgorithmMatches(const CryptoAlgorithmAesCbcParamsDeprecated&, const CryptoKey& key) const
60 {
61     if (key.algorithmIdentifier() != s_identifier)
62         return false;
63     ASSERT(is<CryptoKeyAES>(key));
64     return true;
65 }
66
67 void CryptoAlgorithmAES_CBC::generateKey(const std::unique_ptr<CryptoAlgorithmParameters>&& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyOrKeyPairCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext&)
68 {
69     auto& aesParameters = downcast<CryptoAlgorithmAesKeyGenParams>(*parameters);
70
71     if (usagesAreInvalidForCryptoAlgorithmAES_CBC(usages)) {
72         exceptionCallback(SYNTAX_ERR);
73         return;
74     }
75
76     auto result = CryptoKeyAES::generate(CryptoAlgorithmIdentifier::AES_CBC, aesParameters.length, extractable, usages);
77     if (!result) {
78         exceptionCallback(OperationError);
79         return;
80     }
81
82     callback(result.get(), nullptr);
83 }
84
85 void CryptoAlgorithmAES_CBC::importKey(SubtleCrypto::KeyFormat format, KeyData&& data, const std::unique_ptr<CryptoAlgorithmParameters>&& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyCallback&& callback, ExceptionCallback&& exceptionCallback)
86 {
87     if (usagesAreInvalidForCryptoAlgorithmAES_CBC(usages)) {
88         exceptionCallback(SYNTAX_ERR);
89         return;
90     }
91
92     RefPtr<CryptoKeyAES> result;
93     switch (format) {
94     case SubtleCrypto::KeyFormat::Raw:
95         result = CryptoKeyAES::importRaw(parameters->identifier, WTFMove(WTF::get<Vector<uint8_t>>(data)), extractable, usages);
96         break;
97     case SubtleCrypto::KeyFormat::Jwk: {
98         auto checkAlgCallback = [](size_t length, const Optional<String>& alg) -> bool {
99             switch (length) {
100             case CryptoKeyAES::s_length128:
101                 return !alg || alg.value() == ALG128;
102             case CryptoKeyAES::s_length192:
103                 return !alg || alg.value() == ALG192;
104             case CryptoKeyAES::s_length256:
105                 return !alg || alg.value() == ALG256;
106             }
107             return false;
108         };
109         result = CryptoKeyAES::importJwk(parameters->identifier, WTFMove(WTF::get<JsonWebKey>(data)), extractable, usages, WTFMove(checkAlgCallback));
110         break;
111     }
112     default:
113         exceptionCallback(NOT_SUPPORTED_ERR);
114         return;
115     }
116     if (!result) {
117         exceptionCallback(DataError);
118         return;
119     }
120
121     callback(*result);
122 }
123
124 void CryptoAlgorithmAES_CBC::exportKey(SubtleCrypto::KeyFormat format, RefPtr<CryptoKey>&& key, KeyDataCallback&& callback, ExceptionCallback&& exceptionCallback)
125 {
126     const auto& aesKey = downcast<CryptoKeyAES>(*key);
127
128     if (aesKey.key().isEmpty()) {
129         exceptionCallback(OperationError);
130         return;
131     }
132
133     KeyData result;
134     switch (format) {
135     case SubtleCrypto::KeyFormat::Raw:
136         result = Vector<uint8_t>(aesKey.key());
137         break;
138     case SubtleCrypto::KeyFormat::Jwk: {
139         JsonWebKey jwk = aesKey.exportJwk();
140         switch (aesKey.key().size() * 8) {
141         case CryptoKeyAES::s_length128:
142             jwk.alg = String(ALG128);
143             break;
144         case CryptoKeyAES::s_length192:
145             jwk.alg = String(ALG192);
146             break;
147         case CryptoKeyAES::s_length256:
148             jwk.alg = String(ALG256);
149             break;
150         default:
151             ASSERT_NOT_REACHED();
152         }
153         result = WTFMove(jwk);
154         break;
155     }
156     default:
157         exceptionCallback(NOT_SUPPORTED_ERR);
158         return;
159     }
160
161     callback(format, WTFMove(result));
162 }
163
164 ExceptionOr<void> CryptoAlgorithmAES_CBC::encrypt(const CryptoAlgorithmParametersDeprecated& parameters, const CryptoKey& key, const CryptoOperationData& data, VectorCallback&& callback, VoidCallback&& failureCallback)
165 {
166     auto& aesCBCParameters = downcast<CryptoAlgorithmAesCbcParamsDeprecated>(parameters);
167     if (!keyAlgorithmMatches(aesCBCParameters, key))
168         return Exception { NOT_SUPPORTED_ERR };
169     return platformEncrypt(aesCBCParameters, downcast<CryptoKeyAES>(key), data, WTFMove(callback), WTFMove(failureCallback));
170 }
171
172 ExceptionOr<void> CryptoAlgorithmAES_CBC::decrypt(const CryptoAlgorithmParametersDeprecated& parameters, const CryptoKey& key, const CryptoOperationData& data, VectorCallback&& callback, VoidCallback&& failureCallback)
173 {
174     auto& aesCBCParameters = downcast<CryptoAlgorithmAesCbcParamsDeprecated>(parameters);
175     if (!keyAlgorithmMatches(aesCBCParameters, key))
176         return Exception { NOT_SUPPORTED_ERR };
177     return platformDecrypt(aesCBCParameters, downcast<CryptoKeyAES>(key), data, WTFMove(callback), WTFMove(failureCallback));
178 }
179
180 ExceptionOr<void> CryptoAlgorithmAES_CBC::generateKey(const CryptoAlgorithmParametersDeprecated& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyOrKeyPairCallback&& callback, VoidCallback&& failureCallback, ScriptExecutionContext&)
181 {
182     auto& aesParameters = downcast<CryptoAlgorithmAesKeyGenParamsDeprecated>(parameters);
183
184     auto result = CryptoKeyAES::generate(CryptoAlgorithmIdentifier::AES_CBC, aesParameters.length, extractable, usages);
185     if (!result) {
186         failureCallback();
187         return { };
188     }
189
190     callback(result.get(), nullptr);
191     return { };
192 }
193
194 ExceptionOr<void> CryptoAlgorithmAES_CBC::importKey(const CryptoAlgorithmParametersDeprecated&, const CryptoKeyData& keyData, bool extractable, CryptoKeyUsageBitmap usage, KeyCallback&& callback, VoidCallback&&)
195 {
196     if (!is<CryptoKeyDataOctetSequence>(keyData))
197         return Exception { NOT_SUPPORTED_ERR };
198     auto& keyDataOctetSequence = downcast<CryptoKeyDataOctetSequence>(keyData);
199     callback(CryptoKeyAES::create(CryptoAlgorithmIdentifier::AES_CBC, keyDataOctetSequence.octetSequence(), extractable, usage));
200     return { };
201 }
202
203 }
204
205 #endif // ENABLE(SUBTLE_CRYPTO)