| Absolute File Name: | /home/qt/qt5_coco/qt5/qtbase/src/corelib/tools/qmessageauthenticationcode.cpp |
| Source code | Switch to Preprocessed file |
| Line | Source | Count | ||||||
|---|---|---|---|---|---|---|---|---|
| 1 | /**************************************************************************** | - | ||||||
| 2 | ** | - | ||||||
| 3 | ** Copyright (C) 2013 Ruslan Nigmatullin <euroelessar@yandex.ru> | - | ||||||
| 4 | ** Contact: http://www.qt.io/licensing/ | - | ||||||
| 5 | ** | - | ||||||
| 6 | ** This file is part of the QtCore module of the Qt Toolkit. | - | ||||||
| 7 | ** | - | ||||||
| 8 | ** $QT_BEGIN_LICENSE:LGPL21$ | - | ||||||
| 9 | ** Commercial License Usage | - | ||||||
| 10 | ** Licensees holding valid commercial Qt licenses may use this file in | - | ||||||
| 11 | ** accordance with the commercial license agreement provided with the | - | ||||||
| 12 | ** Software or, alternatively, in accordance with the terms contained in | - | ||||||
| 13 | ** a written agreement between you and The Qt Company. For licensing terms | - | ||||||
| 14 | ** and conditions see http://www.qt.io/terms-conditions. For further | - | ||||||
| 15 | ** information use the contact form at http://www.qt.io/contact-us. | - | ||||||
| 16 | ** | - | ||||||
| 17 | ** GNU Lesser General Public License Usage | - | ||||||
| 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | - | ||||||
| 19 | ** General Public License version 2.1 or version 3 as published by the Free | - | ||||||
| 20 | ** Software Foundation and appearing in the file LICENSE.LGPLv21 and | - | ||||||
| 21 | ** LICENSE.LGPLv3 included in the packaging of this file. Please review the | - | ||||||
| 22 | ** following information to ensure the GNU Lesser General Public License | - | ||||||
| 23 | ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and | - | ||||||
| 24 | ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | - | ||||||
| 25 | ** | - | ||||||
| 26 | ** As a special exception, The Qt Company gives you certain additional | - | ||||||
| 27 | ** rights. These rights are described in The Qt Company LGPL Exception | - | ||||||
| 28 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | - | ||||||
| 29 | ** | - | ||||||
| 30 | ** $QT_END_LICENSE$ | - | ||||||
| 31 | ** | - | ||||||
| 32 | ****************************************************************************/ | - | ||||||
| 33 | - | |||||||
| 34 | #include "qmessageauthenticationcode.h" | - | ||||||
| 35 | #include "qvarlengtharray.h" | - | ||||||
| 36 | - | |||||||
| 37 | /* | - | ||||||
| 38 | These #defines replace the typedefs needed by the RFC6234 code. Normally | - | ||||||
| 39 | the typedefs would come from from stdint.h, but since this header is not | - | ||||||
| 40 | available on all platforms (MSVC 2008, for example), we #define them to the | - | ||||||
| 41 | Qt equivalents. | - | ||||||
| 42 | */ | - | ||||||
| 43 | - | |||||||
| 44 | #ifdef uint64_t | - | ||||||
| 45 | #undef uint64_t | - | ||||||
| 46 | #endif | - | ||||||
| 47 | - | |||||||
| 48 | #define uint64_t QT_PREPEND_NAMESPACE(quint64) | - | ||||||
| 49 | - | |||||||
| 50 | #ifdef uint32_t | - | ||||||
| 51 | #undef uint32_t | - | ||||||
| 52 | #endif | - | ||||||
| 53 | - | |||||||
| 54 | #define uint32_t QT_PREPEND_NAMESPACE(quint32) | - | ||||||
| 55 | - | |||||||
| 56 | #ifdef uint8_t | - | ||||||
| 57 | #undef uint8_t | - | ||||||
| 58 | #endif | - | ||||||
| 59 | - | |||||||
| 60 | #define uint8_t QT_PREPEND_NAMESPACE(quint8) | - | ||||||
| 61 | - | |||||||
| 62 | #ifdef int_least16_t | - | ||||||
| 63 | #undef int_least16_t | - | ||||||
| 64 | #endif | - | ||||||
| 65 | - | |||||||
| 66 | #define int_least16_t QT_PREPEND_NAMESPACE(qint16) | - | ||||||
| 67 | - | |||||||
| 68 | // Header from rfc6234 with 1 modification: | - | ||||||
| 69 | // sha1.h - commented out '#include <stdint.h>' on line 74 | - | ||||||
| 70 | #include "../../3rdparty/rfc6234/sha.h" | - | ||||||
| 71 | - | |||||||
| 72 | #undef uint64_t | - | ||||||
| 73 | #undef uint32_t | - | ||||||
| 74 | #undef uint68_t | - | ||||||
| 75 | #undef int_least16_t | - | ||||||
| 76 | - | |||||||
| 77 | QT_BEGIN_NAMESPACE | - | ||||||
| 78 | - | |||||||
| 79 | static int qt_hash_block_size(QCryptographicHash::Algorithm method) | - | ||||||
| 80 | { | - | ||||||
| 81 | switch (method) { | - | ||||||
| 82 | case QCryptographicHash::Md4: never executed: case QCryptographicHash::Md4: | 0 | ||||||
| 83 | return 64; never executed: return 64; | 0 | ||||||
| 84 | case QCryptographicHash::Md5: executed 20 times by 1 test: case QCryptographicHash::Md5:Executed by:
| 20 | ||||||
| 85 | return 64; executed 20 times by 1 test: return 64;Executed by:
| 20 | ||||||
| 86 | case QCryptographicHash::Sha1: executed 8 times by 1 test: case QCryptographicHash::Sha1:Executed by:
| 8 | ||||||
| 87 | return SHA1_Message_Block_Size; executed 8 times by 1 test: return SHA1_Message_Block_Size;Executed by:
| 8 | ||||||
| 88 | case QCryptographicHash::Sha224: never executed: case QCryptographicHash::Sha224: | 0 | ||||||
| 89 | return SHA224_Message_Block_Size; never executed: return SHA224_Message_Block_Size; | 0 | ||||||
| 90 | case QCryptographicHash::Sha256: executed 8 times by 1 test: case QCryptographicHash::Sha256:Executed by:
| 8 | ||||||
| 91 | return SHA256_Message_Block_Size; executed 8 times by 1 test: return SHA256_Message_Block_Size;Executed by:
| 8 | ||||||
| 92 | case QCryptographicHash::Sha384: never executed: case QCryptographicHash::Sha384: | 0 | ||||||
| 93 | return SHA384_Message_Block_Size; never executed: return SHA384_Message_Block_Size; | 0 | ||||||
| 94 | case QCryptographicHash::Sha512: never executed: case QCryptographicHash::Sha512: | 0 | ||||||
| 95 | return SHA512_Message_Block_Size; never executed: return SHA512_Message_Block_Size; | 0 | ||||||
| 96 | case QCryptographicHash::Sha3_224: never executed: case QCryptographicHash::Sha3_224: | 0 | ||||||
| 97 | return 144; never executed: return 144; | 0 | ||||||
| 98 | case QCryptographicHash::Sha3_256: never executed: case QCryptographicHash::Sha3_256: | 0 | ||||||
| 99 | return 136; never executed: return 136; | 0 | ||||||
| 100 | case QCryptographicHash::Sha3_384: never executed: case QCryptographicHash::Sha3_384: | 0 | ||||||
| 101 | return 104; never executed: return 104; | 0 | ||||||
| 102 | case QCryptographicHash::Sha3_512: never executed: case QCryptographicHash::Sha3_512: | 0 | ||||||
| 103 | return 72; never executed: return 72; | 0 | ||||||
| 104 | } | - | ||||||
| 105 | return 0; never executed: return 0; | 0 | ||||||
| 106 | } | - | ||||||
| 107 | - | |||||||
| 108 | class QMessageAuthenticationCodePrivate | - | ||||||
| 109 | { | - | ||||||
| 110 | public: | - | ||||||
| 111 | QMessageAuthenticationCodePrivate(QCryptographicHash::Algorithm m) | - | ||||||
| 112 | : messageHash(m), method(m), messageHashInited(false) | - | ||||||
| 113 | { | - | ||||||
| 114 | } executed 18 times by 1 test: end of blockExecuted by:
| 18 | ||||||
| 115 | - | |||||||
| 116 | QByteArray key; | - | ||||||
| 117 | QByteArray result; | - | ||||||
| 118 | QCryptographicHash messageHash; | - | ||||||
| 119 | QCryptographicHash::Algorithm method; | - | ||||||
| 120 | bool messageHashInited; | - | ||||||
| 121 | - | |||||||
| 122 | void initMessageHash(); | - | ||||||
| 123 | }; | - | ||||||
| 124 | - | |||||||
| 125 | void QMessageAuthenticationCodePrivate::initMessageHash() | - | ||||||
| 126 | { | - | ||||||
| 127 | if (messageHashInited)
| 18-27 | ||||||
| 128 | return; executed 27 times by 1 test: return;Executed by:
| 27 | ||||||
| 129 | messageHashInited = true; | - | ||||||
| 130 | - | |||||||
| 131 | const int blockSize = qt_hash_block_size(method); | - | ||||||
| 132 | - | |||||||
| 133 | if (key.size() > blockSize) {
| 0-18 | ||||||
| 134 | QCryptographicHash hash(method); | - | ||||||
| 135 | hash.addData(key); | - | ||||||
| 136 | key = hash.result(); | - | ||||||
| 137 | hash.reset(); | - | ||||||
| 138 | } never executed: end of block | 0 | ||||||
| 139 | - | |||||||
| 140 | if (key.size() < blockSize) {
| 0-18 | ||||||
| 141 | const int size = key.size(); | - | ||||||
| 142 | key.resize(blockSize); | - | ||||||
| 143 | memset(key.data() + size, 0, blockSize - size); | - | ||||||
| 144 | } executed 18 times by 1 test: end of blockExecuted by:
| 18 | ||||||
| 145 | - | |||||||
| 146 | QVarLengthArray<char> iKeyPad(blockSize); | - | ||||||
| 147 | const char * const keyData = key.constData(); | - | ||||||
| 148 | - | |||||||
| 149 | for (int i = 0; i < blockSize; ++i)
| 18-1152 | ||||||
| 150 | iKeyPad[i] = keyData[i] ^ 0x36; executed 1152 times by 1 test: iKeyPad[i] = keyData[i] ^ 0x36;Executed by:
| 1152 | ||||||
| 151 | - | |||||||
| 152 | messageHash.addData(iKeyPad.data(), iKeyPad.size()); | - | ||||||
| 153 | } executed 18 times by 1 test: end of blockExecuted by:
| 18 | ||||||
| 154 | - | |||||||
| 155 | /*! | - | ||||||
| 156 | \class QMessageAuthenticationCode | - | ||||||
| 157 | \inmodule QtCore | - | ||||||
| 158 | - | |||||||
| 159 | \brief The QMessageAuthenticationCode class provides a way to generate | - | ||||||
| 160 | hash-based message authentication codes. | - | ||||||
| 161 | - | |||||||
| 162 | \since 5.1 | - | ||||||
| 163 | - | |||||||
| 164 | \ingroup tools | - | ||||||
| 165 | \reentrant | - | ||||||
| 166 | - | |||||||
| 167 | QMessageAuthenticationCode supports all cryptographic hashes which are supported by | - | ||||||
| 168 | QCryptographicHash. | - | ||||||
| 169 | - | |||||||
| 170 | To generate message authentication code, pass hash algorithm QCryptographicHash::Algorithm | - | ||||||
| 171 | to constructor, then set key and message by setKey() and addData() functions. Result | - | ||||||
| 172 | can be acquired by result() function. | - | ||||||
| 173 | \snippet qmessageauthenticationcode/main.cpp 0 | - | ||||||
| 174 | \dots | - | ||||||
| 175 | \snippet qmessageauthenticationcode/main.cpp 1 | - | ||||||
| 176 | - | |||||||
| 177 | Alternatively, this effect can be achieved by providing message, | - | ||||||
| 178 | key and method to hash() method. | - | ||||||
| 179 | \snippet qmessageauthenticationcode/main.cpp 2 | - | ||||||
| 180 | - | |||||||
| 181 | \sa QCryptographicHash | - | ||||||
| 182 | */ | - | ||||||
| 183 | - | |||||||
| 184 | /*! | - | ||||||
| 185 | Constructs an object that can be used to create a cryptographic hash from data | - | ||||||
| 186 | using method \a method and key \a key. | - | ||||||
| 187 | */ | - | ||||||
| 188 | QMessageAuthenticationCode::QMessageAuthenticationCode(QCryptographicHash::Algorithm method, | - | ||||||
| 189 | const QByteArray &key) | - | ||||||
| 190 | : d(new QMessageAuthenticationCodePrivate(method)) | - | ||||||
| 191 | { | - | ||||||
| 192 | d->key = key; | - | ||||||
| 193 | } executed 18 times by 1 test: end of blockExecuted by:
| 18 | ||||||
| 194 | - | |||||||
| 195 | /*! | - | ||||||
| 196 | Destroys the object. | - | ||||||
| 197 | */ | - | ||||||
| 198 | QMessageAuthenticationCode::~QMessageAuthenticationCode() | - | ||||||
| 199 | { | - | ||||||
| 200 | delete d; | - | ||||||
| 201 | } executed 18 times by 1 test: end of blockExecuted by:
| 18 | ||||||
| 202 | - | |||||||
| 203 | /*! | - | ||||||
| 204 | Resets message data. Calling this method doesn't affect the key. | - | ||||||
| 205 | */ | - | ||||||
| 206 | void QMessageAuthenticationCode::reset() | - | ||||||
| 207 | { | - | ||||||
| 208 | d->result.clear(); | - | ||||||
| 209 | d->messageHash.reset(); | - | ||||||
| 210 | d->messageHashInited = false; | - | ||||||
| 211 | } executed 18 times by 1 test: end of blockExecuted by:
| 18 | ||||||
| 212 | - | |||||||
| 213 | /*! | - | ||||||
| 214 | Sets secret \a key. Calling this method automatically resets the object state. | - | ||||||
| 215 | */ | - | ||||||
| 216 | void QMessageAuthenticationCode::setKey(const QByteArray &key) | - | ||||||
| 217 | { | - | ||||||
| 218 | reset(); | - | ||||||
| 219 | d->key = key; | - | ||||||
| 220 | } executed 18 times by 1 test: end of blockExecuted by:
| 18 | ||||||
| 221 | - | |||||||
| 222 | /*! | - | ||||||
| 223 | Adds the first \a length chars of \a data to the message. | - | ||||||
| 224 | */ | - | ||||||
| 225 | void QMessageAuthenticationCode::addData(const char *data, int length) | - | ||||||
| 226 | { | - | ||||||
| 227 | d->initMessageHash(); | - | ||||||
| 228 | d->messageHash.addData(data, length); | - | ||||||
| 229 | } never executed: end of block | 0 | ||||||
| 230 | - | |||||||
| 231 | /*! | - | ||||||
| 232 | \overload addData() | - | ||||||
| 233 | */ | - | ||||||
| 234 | void QMessageAuthenticationCode::addData(const QByteArray &data) | - | ||||||
| 235 | { | - | ||||||
| 236 | d->initMessageHash(); | - | ||||||
| 237 | d->messageHash.addData(data); | - | ||||||
| 238 | } executed 27 times by 1 test: end of blockExecuted by:
| 27 | ||||||
| 239 | - | |||||||
| 240 | /*! | - | ||||||
| 241 | Reads the data from the open QIODevice \a device until it ends | - | ||||||
| 242 | and adds it to message. Returns \c true if reading was successful. | - | ||||||
| 243 | - | |||||||
| 244 | \note \a device must be already opened. | - | ||||||
| 245 | */ | - | ||||||
| 246 | bool QMessageAuthenticationCode::addData(QIODevice *device) | - | ||||||
| 247 | { | - | ||||||
| 248 | d->initMessageHash(); | - | ||||||
| 249 | return d->messageHash.addData(device); never executed: return d->messageHash.addData(device); | 0 | ||||||
| 250 | } | - | ||||||
| 251 | - | |||||||
| 252 | /*! | - | ||||||
| 253 | Returns the final authentication code. | - | ||||||
| 254 | - | |||||||
| 255 | \sa QByteArray::toHex() | - | ||||||
| 256 | */ | - | ||||||
| 257 | QByteArray QMessageAuthenticationCode::result() const | - | ||||||
| 258 | { | - | ||||||
| 259 | if (!d->result.isEmpty())
| 0-18 | ||||||
| 260 | return d->result; never executed: return d->result; | 0 | ||||||
| 261 | - | |||||||
| 262 | d->initMessageHash(); | - | ||||||
| 263 | - | |||||||
| 264 | const int blockSize = qt_hash_block_size(d->method); | - | ||||||
| 265 | - | |||||||
| 266 | QByteArray hashedMessage = d->messageHash.result(); | - | ||||||
| 267 | - | |||||||
| 268 | QVarLengthArray<char> oKeyPad(blockSize); | - | ||||||
| 269 | const char * const keyData = d->key.constData(); | - | ||||||
| 270 | - | |||||||
| 271 | for (int i = 0; i < blockSize; ++i)
| 18-1152 | ||||||
| 272 | oKeyPad[i] = keyData[i] ^ 0x5c; executed 1152 times by 1 test: oKeyPad[i] = keyData[i] ^ 0x5c;Executed by:
| 1152 | ||||||
| 273 | - | |||||||
| 274 | QCryptographicHash hash(d->method); | - | ||||||
| 275 | hash.addData(oKeyPad.data(), oKeyPad.size()); | - | ||||||
| 276 | hash.addData(hashedMessage); | - | ||||||
| 277 | - | |||||||
| 278 | d->result = hash.result(); | - | ||||||
| 279 | return d->result; executed 18 times by 1 test: return d->result;Executed by:
| 18 | ||||||
| 280 | } | - | ||||||
| 281 | - | |||||||
| 282 | /*! | - | ||||||
| 283 | Returns the authentication code for the message \a message using | - | ||||||
| 284 | the key \a key and the method \a method. | - | ||||||
| 285 | */ | - | ||||||
| 286 | QByteArray QMessageAuthenticationCode::hash(const QByteArray &message, const QByteArray &key, | - | ||||||
| 287 | QCryptographicHash::Algorithm method) | - | ||||||
| 288 | { | - | ||||||
| 289 | QMessageAuthenticationCode mac(method); | - | ||||||
| 290 | mac.setKey(key); | - | ||||||
| 291 | mac.addData(message); | - | ||||||
| 292 | return mac.result(); never executed: return mac.result(); | 0 | ||||||
| 293 | } | - | ||||||
| 294 | - | |||||||
| 295 | QT_END_NAMESPACE | - | ||||||
| Source code | Switch to Preprocessed file |