2 * Copyright (C) 2013 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "CryptoAlgorithmHMAC.h"
29 #if ENABLE(SUBTLE_CRYPTO)
31 #include "CryptoAlgorithmHmacParams.h"
32 #include "CryptoKeyHMAC.h"
33 #include "ExceptionCode.h"
34 #include "JSDOMPromise.h"
35 #include <CommonCrypto/CommonHMAC.h>
39 static bool getCommonCryptoAlgorithm(CryptoAlgorithmIdentifier hashFunction, CCHmacAlgorithm& algorithm)
41 switch (hashFunction) {
42 case CryptoAlgorithmIdentifier::SHA_1:
43 algorithm = kCCHmacAlgSHA1;
45 case CryptoAlgorithmIdentifier::SHA_224:
46 algorithm = kCCHmacAlgSHA224;
48 case CryptoAlgorithmIdentifier::SHA_256:
49 algorithm = kCCHmacAlgSHA256;
51 case CryptoAlgorithmIdentifier::SHA_384:
52 algorithm = kCCHmacAlgSHA384;
54 case CryptoAlgorithmIdentifier::SHA_512:
55 algorithm = kCCHmacAlgSHA512;
62 static Vector<unsigned char> calculateSignature(CCHmacAlgorithm algorithm, const Vector<char>& key, const CryptoOperationData& data)
67 digestLength = CC_SHA1_DIGEST_LENGTH;
69 case kCCHmacAlgSHA224:
70 digestLength = CC_SHA224_DIGEST_LENGTH;
72 case kCCHmacAlgSHA256:
73 digestLength = CC_SHA256_DIGEST_LENGTH;
75 case kCCHmacAlgSHA384:
76 digestLength = CC_SHA384_DIGEST_LENGTH;
78 case kCCHmacAlgSHA512:
79 digestLength = CC_SHA512_DIGEST_LENGTH;
85 Vector<unsigned char> result(digestLength);
86 const char* keyData = key.data() ? key.data() : ""; // <rdar://problem/15467425> HMAC crashes when key pointer is null.
87 CCHmac(algorithm, keyData, key.size(), data.first, data.second, result.data());
91 void CryptoAlgorithmHMAC::sign(const CryptoAlgorithmParameters& parameters, const CryptoKey& key, const CryptoOperationData& data, std::unique_ptr<PromiseWrapper> promise, ExceptionCode& ec)
93 const CryptoAlgorithmHmacParams& hmacParameters = toCryptoAlgorithmHmacParams(parameters);
95 if (!isCryptoKeyHMAC(key)) {
96 ec = NOT_SUPPORTED_ERR;
99 const CryptoKeyHMAC& hmacKey = toCryptoKeyHMAC(key);
101 CCHmacAlgorithm algorithm;
102 if (!getCommonCryptoAlgorithm(hmacParameters.hash, algorithm)) {
103 ec = NOT_SUPPORTED_ERR;
107 Vector<unsigned char> signature = calculateSignature(algorithm, hmacKey.key(), data);
109 promise->fulfill(signature);
112 void CryptoAlgorithmHMAC::verify(const CryptoAlgorithmParameters& parameters, const CryptoKey& key, const CryptoOperationData& expectedSignature, const CryptoOperationData& data, std::unique_ptr<PromiseWrapper> promise, ExceptionCode& ec)
114 const CryptoAlgorithmHmacParams& hmacParameters = toCryptoAlgorithmHmacParams(parameters);
116 if (!isCryptoKeyHMAC(key)) {
117 ec = NOT_SUPPORTED_ERR;
120 const CryptoKeyHMAC& hmacKey = toCryptoKeyHMAC(key);
122 CCHmacAlgorithm algorithm;
123 if (!getCommonCryptoAlgorithm(hmacParameters.hash, algorithm)) {
124 ec = NOT_SUPPORTED_ERR;
128 Vector<unsigned char> signature = calculateSignature(algorithm, hmacKey.key(), data);
130 bool result = signature.size() == expectedSignature.second && !memcmp(signature.data(), expectedSignature.first, signature.size());
132 promise->fulfill(result);
137 #endif // ENABLE(SUBTLE_CRYPTO)