Use Optional::valueOr() instead of Optional::value_or()
[WebKit-https.git] / Source / WebCore / crypto / algorithms / CryptoAlgorithmHMAC.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 "CryptoAlgorithmHMAC.h"
28
29 #if ENABLE(WEB_CRYPTO)
30
31 #include "CryptoAlgorithmHmacKeyParams.h"
32 #include "CryptoKeyHMAC.h"
33 #include <wtf/Variant.h>
34
35 namespace WebCore {
36
37 namespace CryptoAlgorithmHMACInternal {
38 static const char* const ALG1 = "HS1";
39 static const char* const ALG224 = "HS224";
40 static const char* const ALG256 = "HS256";
41 static const char* const ALG384 = "HS384";
42 static const char* const ALG512 = "HS512";
43 }
44
45 static inline bool usagesAreInvalidForCryptoAlgorithmHMAC(CryptoKeyUsageBitmap usages)
46 {
47     return usages & (CryptoKeyUsageEncrypt | CryptoKeyUsageDecrypt | CryptoKeyUsageDeriveKey | CryptoKeyUsageDeriveBits | CryptoKeyUsageWrapKey | CryptoKeyUsageUnwrapKey);
48 }
49
50 Ref<CryptoAlgorithm> CryptoAlgorithmHMAC::create()
51 {
52     return adoptRef(*new CryptoAlgorithmHMAC);
53 }
54
55 CryptoAlgorithmIdentifier CryptoAlgorithmHMAC::identifier() const
56 {
57     return s_identifier;
58 }
59
60 void CryptoAlgorithmHMAC::sign(const CryptoAlgorithmParameters&, Ref<CryptoKey>&& key, Vector<uint8_t>&& data, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue)
61 {
62     dispatchOperationInWorkQueue(workQueue, context, WTFMove(callback), WTFMove(exceptionCallback),
63         [key = WTFMove(key), data = WTFMove(data)] {
64             return platformSign(downcast<CryptoKeyHMAC>(key.get()), data);
65         });
66 }
67
68 void CryptoAlgorithmHMAC::verify(const CryptoAlgorithmParameters&, Ref<CryptoKey>&& key, Vector<uint8_t>&& signature, Vector<uint8_t>&& data, BoolCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue)
69 {
70     dispatchOperationInWorkQueue(workQueue, context, WTFMove(callback), WTFMove(exceptionCallback),
71         [key = WTFMove(key), signature = WTFMove(signature), data = WTFMove(data)] {
72             return platformVerify(downcast<CryptoKeyHMAC>(key.get()), signature, data);
73         });
74 }
75
76 void CryptoAlgorithmHMAC::generateKey(const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyOrKeyPairCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext&)
77 {
78     const auto& hmacParameters = downcast<CryptoAlgorithmHmacKeyParams>(parameters);
79
80     if (usagesAreInvalidForCryptoAlgorithmHMAC(usages)) {
81         exceptionCallback(SyntaxError);
82         return;
83     }
84
85     if (hmacParameters.length && !hmacParameters.length.value()) {
86         exceptionCallback(OperationError);
87         return;
88     }
89
90     auto result = CryptoKeyHMAC::generate(hmacParameters.length.valueOr(0), hmacParameters.hashIdentifier, extractable, usages);
91     if (!result) {
92         exceptionCallback(OperationError);
93         return;
94     }
95
96     callback(WTFMove(result));
97 }
98
99 void CryptoAlgorithmHMAC::importKey(CryptoKeyFormat format, KeyData&& data, const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyCallback&& callback, ExceptionCallback&& exceptionCallback)
100 {
101     using namespace CryptoAlgorithmHMACInternal;
102
103     const auto& hmacParameters = downcast<CryptoAlgorithmHmacKeyParams>(parameters);
104
105     if (usagesAreInvalidForCryptoAlgorithmHMAC(usages)) {
106         exceptionCallback(SyntaxError);
107         return;
108     }
109
110     RefPtr<CryptoKeyHMAC> result;
111     switch (format) {
112     case CryptoKeyFormat::Raw:
113         result = CryptoKeyHMAC::importRaw(hmacParameters.length.valueOr(0), hmacParameters.hashIdentifier, WTFMove(WTF::get<Vector<uint8_t>>(data)), extractable, usages);
114         break;
115     case CryptoKeyFormat::Jwk: {
116         auto checkAlgCallback = [](CryptoAlgorithmIdentifier hash, const String& alg) -> bool {
117             switch (hash) {
118             case CryptoAlgorithmIdentifier::SHA_1:
119                 return alg.isNull() || alg == ALG1;
120             case CryptoAlgorithmIdentifier::SHA_224:
121                 return alg.isNull() || alg == ALG224;
122             case CryptoAlgorithmIdentifier::SHA_256:
123                 return alg.isNull() || alg == ALG256;
124             case CryptoAlgorithmIdentifier::SHA_384:
125                 return alg.isNull() || alg == ALG384;
126             case CryptoAlgorithmIdentifier::SHA_512:
127                 return alg.isNull() || alg == ALG512;
128             default:
129                 return false;
130             }
131             return false;
132         };
133         result = CryptoKeyHMAC::importJwk(hmacParameters.length.valueOr(0), hmacParameters.hashIdentifier, WTFMove(WTF::get<JsonWebKey>(data)), extractable, usages, WTFMove(checkAlgCallback));
134         break;
135     }
136     default:
137         exceptionCallback(NotSupportedError);
138         return;
139     }
140     if (!result) {
141         exceptionCallback(DataError);
142         return;
143     }
144
145     callback(*result);
146 }
147
148 void CryptoAlgorithmHMAC::exportKey(CryptoKeyFormat format, Ref<CryptoKey>&& key, KeyDataCallback&& callback, ExceptionCallback&& exceptionCallback)
149 {
150     using namespace CryptoAlgorithmHMACInternal;
151     const auto& hmacKey = downcast<CryptoKeyHMAC>(key.get());
152
153     if (hmacKey.key().isEmpty()) {
154         exceptionCallback(OperationError);
155         return;
156     }
157
158     KeyData result;
159     switch (format) {
160     case CryptoKeyFormat::Raw:
161         result = Vector<uint8_t>(hmacKey.key());
162         break;
163     case CryptoKeyFormat::Jwk: {
164         JsonWebKey jwk = hmacKey.exportJwk();
165         switch (hmacKey.hashAlgorithmIdentifier()) {
166         case CryptoAlgorithmIdentifier::SHA_1:
167             jwk.alg = String(ALG1);
168             break;
169         case CryptoAlgorithmIdentifier::SHA_224:
170             jwk.alg = String(ALG224);
171             break;
172         case CryptoAlgorithmIdentifier::SHA_256:
173             jwk.alg = String(ALG256);
174             break;
175         case CryptoAlgorithmIdentifier::SHA_384:
176             jwk.alg = String(ALG384);
177             break;
178         case CryptoAlgorithmIdentifier::SHA_512:
179             jwk.alg = String(ALG512);
180             break;
181         default:
182             ASSERT_NOT_REACHED();
183         }
184         result = WTFMove(jwk);
185         break;
186     }
187     default:
188         exceptionCallback(NotSupportedError);
189         return;
190     }
191
192     callback(format, WTFMove(result));
193 }
194
195 ExceptionOr<size_t> CryptoAlgorithmHMAC::getKeyLength(const CryptoAlgorithmParameters& parameters)
196 {
197     return CryptoKeyHMAC::getKeyLength(parameters);
198 }
199
200 }
201
202 #endif // ENABLE(WEB_CRYPTO)