Changeset 214822 in webkit
- Timestamp:
- Apr 3, 2017 11:12:38 AM (7 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r214821 r214822 1 2017-04-03 Zan Dobersek <zdobersek@igalia.com> 2 3 [GCrypt] Implement AES_GCM support 4 https://bugs.webkit.org/show_bug.cgi?id=170271 5 6 Reviewed by Michael Catanzaro. 7 8 Implement the CryptoAlgorithmAES_GCM::platform{Encrypt,Decrypt} 9 functionality for configurations that use libgcrypt. This is done 10 by leveraging the gcry_cipher_* APIs for the AES algorithm that's 11 deducted appropriately from the key size and the GCM cipher mode. 12 13 No new tests -- current ones cover this sufficiently, but are not yet 14 enabled due to other missing platform-specific SUBTLE_CRYPTO 15 implementations. 16 17 * crypto/gcrypt/CryptoAlgorithmAES_GCMGCrypt.cpp: 18 (WebCore::gcryptEncrypt): 19 (WebCore::gcryptDecrypt): 20 (WebCore::CryptoAlgorithmAES_GCM::platformEncrypt): 21 (WebCore::CryptoAlgorithmAES_GCM::platformDecrypt): 22 1 23 2017-04-03 Zan Dobersek <zdobersek@igalia.com> 2 24 -
trunk/Source/WebCore/PAL/ChangeLog
r214609 r214822 1 2017-04-03 Zan Dobersek <zdobersek@igalia.com> 2 3 [GCrypt] Implement AES_GCM support 4 https://bugs.webkit.org/show_bug.cgi?id=170271 5 6 Reviewed by Michael Catanzaro. 7 8 * pal/crypto/gcrypt/Handle.h: 9 (PAL::GCrypt::HandleDeleter<gcry_cipher_hd_t>::operator()): Specialize 10 the HandleDeleter<> template for the gcry_cipher_hd_t type. 11 1 12 2017-03-30 Zan Dobersek <zdobersek@igalia.com> 2 13 -
trunk/Source/WebCore/PAL/pal/crypto/gcrypt/Handle.h
r214550 r214822 84 84 85 85 template<> 86 struct HandleDeleter<gcry_cipher_hd_t> { 87 void operator()(gcry_cipher_hd_t handle) 88 { 89 gcry_cipher_close(handle); 90 } 91 }; 92 93 template<> 86 94 struct HandleDeleter<gcry_mac_hd_t> { 87 95 void operator()(gcry_mac_hd_t handle) -
trunk/Source/WebCore/crypto/gcrypt/CryptoAlgorithmAES_GCMGCrypt.cpp
r214538 r214822 1 1 /* 2 2 * Copyright (C) 2017 Apple Inc. All rights reserved. 3 * Copyright (C) 2017 Metrological Group B.V. 4 * Copyright (C) 2017 Igalia S.L. 3 5 * 4 6 * Redistribution and use in source and binary forms, with or without … … 29 31 #if ENABLE(SUBTLE_CRYPTO) 30 32 33 #include "CryptoAlgorithmAesGcmParams.h" 34 #include "CryptoKeyAES.h" 31 35 #include "ExceptionCode.h" 32 36 #include "NotImplemented.h" 37 #include "ScriptExecutionContext.h" 38 #include <pal/crypto/gcrypt/Handle.h> 39 #include <pal/crypto/gcrypt/Utilities.h> 40 #include <wtf/CryptographicUtilities.h> 33 41 34 42 namespace WebCore { 35 43 36 void CryptoAlgorithmAES_GCM::platformEncrypt(std::unique_ptr<CryptoAlgorithmParameters>&&, Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) 37 { 38 notImplemented(); 39 } 40 41 void CryptoAlgorithmAES_GCM::platformDecrypt(std::unique_ptr<CryptoAlgorithmParameters>&&, Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) 42 { 43 notImplemented(); 44 static std::optional<Vector<uint8_t>> gcryptEncrypt(const Vector<uint8_t>& key, const Vector<uint8_t>& iv, Vector<uint8_t>&& plainText, const Vector<uint8_t>& additionalData, uint8_t tagLength) 45 { 46 auto algorithm = PAL::GCrypt::aesAlgorithmForKeySize(key.size() * 8); 47 if (!algorithm) 48 return std::nullopt; 49 50 PAL::GCrypt::Handle<gcry_cipher_hd_t> handle; 51 gcry_error_t error = gcry_cipher_open(&handle, *algorithm, GCRY_CIPHER_MODE_GCM, GCRY_CIPHER_SECURE); 52 if (error != GPG_ERR_NO_ERROR) { 53 PAL::GCrypt::logError(error); 54 return std::nullopt; 55 } 56 57 error = gcry_cipher_setkey(handle, key.data(), key.size()); 58 if (error != GPG_ERR_NO_ERROR) { 59 PAL::GCrypt::logError(error); 60 return std::nullopt; 61 } 62 63 error = gcry_cipher_setiv(handle, iv.data(), iv.size()); 64 if (error != GPG_ERR_NO_ERROR) { 65 PAL::GCrypt::logError(error); 66 return std::nullopt; 67 } 68 69 if (!additionalData.isEmpty()) { 70 error = gcry_cipher_authenticate(handle, additionalData.data(), additionalData.size()); 71 if (error != GPG_ERR_NO_ERROR) { 72 PAL::GCrypt::logError(error); 73 return std::nullopt; 74 } 75 } 76 77 error = gcry_cipher_final(handle); 78 if (error != GPG_ERR_NO_ERROR) { 79 PAL::GCrypt::logError(error); 80 return std::nullopt; 81 } 82 83 Vector<uint8_t> output(plainText.size()); 84 error = gcry_cipher_encrypt(handle, output.data(), output.size(), plainText.data(), plainText.size()); 85 if (error != GPG_ERR_NO_ERROR) { 86 PAL::GCrypt::logError(error); 87 return std::nullopt; 88 } 89 90 if (tagLength) { 91 Vector<uint8_t> tag(tagLength); 92 error = gcry_cipher_gettag(handle, tag.data(), tag.size()); 93 if (error != GPG_ERR_NO_ERROR) { 94 PAL::GCrypt::logError(error); 95 return std::nullopt; 96 } 97 98 output.appendVector(tag); 99 } 100 101 return output; 102 } 103 104 static std::optional<Vector<uint8_t>> gcryptDecrypt(const Vector<uint8_t>& key, const Vector<uint8_t>& iv, Vector<uint8_t>&& cipherText, const Vector<uint8_t>& additionalData, uint8_t tagLength) 105 { 106 auto algorithm = PAL::GCrypt::aesAlgorithmForKeySize(key.size() * 8); 107 if (!algorithm) 108 return std::nullopt; 109 110 PAL::GCrypt::Handle<gcry_cipher_hd_t> handle; 111 gcry_error_t error = gcry_cipher_open(&handle, *algorithm, GCRY_CIPHER_MODE_GCM, 0); 112 if (error != GPG_ERR_NO_ERROR) { 113 PAL::GCrypt::logError(error); 114 return std::nullopt; 115 } 116 117 error = gcry_cipher_setkey(handle, key.data(), key.size()); 118 if (error != GPG_ERR_NO_ERROR) { 119 PAL::GCrypt::logError(error); 120 return std::nullopt; 121 } 122 123 error = gcry_cipher_setiv(handle, iv.data(), iv.size()); 124 if (error != GPG_ERR_NO_ERROR) { 125 PAL::GCrypt::logError(error); 126 return std::nullopt; 127 } 128 129 if (!additionalData.isEmpty()) { 130 error = gcry_cipher_authenticate(handle, additionalData.data(), additionalData.size()); 131 if (error != GPG_ERR_NO_ERROR) { 132 PAL::GCrypt::logError(error); 133 return std::nullopt; 134 } 135 } 136 137 error = gcry_cipher_final(handle); 138 if (error != GPG_ERR_NO_ERROR) { 139 PAL::GCrypt::logError(error); 140 return std::nullopt; 141 } 142 143 size_t cipherLength = cipherText.size() - tagLength; 144 Vector<uint8_t> output(cipherLength); 145 error = gcry_cipher_decrypt(handle, output.data(), output.size(), cipherText.data(), cipherLength); 146 if (error != GPG_ERR_NO_ERROR) { 147 PAL::GCrypt::logError(error); 148 return std::nullopt; 149 } 150 151 if (tagLength) { 152 Vector<uint8_t> tag(tagLength); 153 error = gcry_cipher_gettag(handle, tag.data(), tagLength); 154 if (error != GPG_ERR_NO_ERROR) { 155 PAL::GCrypt::logError(error); 156 return std::nullopt; 157 } 158 159 if (constantTimeMemcmp(tag.data(), cipherText.data() + cipherLength, tagLength)) 160 return std::nullopt; 161 } 162 163 return output; 164 } 165 166 void CryptoAlgorithmAES_GCM::platformEncrypt(std::unique_ptr<CryptoAlgorithmParameters>&& parameters, Ref<CryptoKey>&& key, Vector<uint8_t>&& plainText, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) 167 { 168 context.ref(); 169 workQueue.dispatch( 170 [parameters = WTFMove(parameters), key = WTFMove(key), plainText = WTFMove(plainText), callback = WTFMove(callback), exceptionCallback = WTFMove(exceptionCallback), &context]() mutable { 171 auto& aesParameters = downcast<CryptoAlgorithmAesGcmParams>(*parameters); 172 auto& aesKey = downcast<CryptoKeyAES>(key.get()); 173 174 auto output = gcryptEncrypt(aesKey.key(), aesParameters.ivVector(), WTFMove(plainText), aesParameters.additionalDataVector(), aesParameters.tagLength.value_or(0) / 8); 175 if (!output) { 176 // We should only dereference callbacks after being back to the Document/Worker threads. 177 context.postTask( 178 [callback = WTFMove(callback), exceptionCallback = WTFMove(exceptionCallback)](ScriptExecutionContext& context) { 179 exceptionCallback(OperationError); 180 context.deref(); 181 }); 182 return; 183 } 184 185 // We should only dereference callbacks after being back to the Document/Worker threads. 186 context.postTask( 187 [output = WTFMove(*output), callback = WTFMove(callback), exceptionCallback = WTFMove(exceptionCallback)](ScriptExecutionContext& context) mutable { 188 callback(WTFMove(output)); 189 context.deref(); 190 }); 191 }); 192 } 193 194 void CryptoAlgorithmAES_GCM::platformDecrypt(std::unique_ptr<CryptoAlgorithmParameters>&& parameters, Ref<CryptoKey>&& key, Vector<uint8_t>&& cipherText, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) 195 { 196 context.ref(); 197 workQueue.dispatch( 198 [parameters = WTFMove(parameters), key = WTFMove(key), cipherText = WTFMove(cipherText), callback = WTFMove(callback), exceptionCallback = WTFMove(exceptionCallback), &context]() mutable { 199 auto& aesParameters = downcast<CryptoAlgorithmAesGcmParams>(*parameters); 200 auto& aesKey = downcast<CryptoKeyAES>(key.get()); 201 202 auto output = gcryptDecrypt(aesKey.key(), aesParameters.ivVector(), WTFMove(cipherText), aesParameters.additionalDataVector(), aesParameters.tagLength.value_or(0) / 8); 203 if (!output) { 204 // We should only dereference callbacks after being back to the Document/Worker threads. 205 context.postTask( 206 [callback = WTFMove(callback), exceptionCallback = WTFMove(exceptionCallback)](ScriptExecutionContext& context) { 207 exceptionCallback(OperationError); 208 context.deref(); 209 }); 210 return; 211 } 212 213 // We should only dereference callbacks after being back to the Document/Worker threads. 214 context.postTask( 215 [output = WTFMove(*output), callback = WTFMove(callback), exceptionCallback = WTFMove(exceptionCallback)](ScriptExecutionContext& context) mutable { 216 callback(WTFMove(output)); 217 context.deref(); 218 }); 219 }); 44 220 } 45 221
Note: See TracChangeset
for help on using the changeset viewer.