From f890856c6d4f5d60719bf350b9a82edcc31561fc Mon Sep 17 00:00:00 2001 From: JoshuaJB Date: Sat, 14 Dec 2013 16:58:21 +0000 Subject: [PATCH] Seperate differently licenced portions of sha.cpp/h into pkcs5_pdkdf2.cpp/h and remove some extra std includes in sha.cpp. Refs #2308 This was SVN commit r14350. --- source/lobby/pkcs5_pbkdf2.cpp | 98 +++++++++++++++++++ source/lobby/pkcs5_pbkdf2.h | 44 +++++++++ source/lobby/scripting/JSInterface_Lobby.cpp | 1 + source/lobby/sha.cpp | 99 +------------------- source/lobby/sha.h | 18 ---- 5 files changed, 144 insertions(+), 116 deletions(-) create mode 100644 source/lobby/pkcs5_pbkdf2.cpp create mode 100644 source/lobby/pkcs5_pbkdf2.h diff --git a/source/lobby/pkcs5_pbkdf2.cpp b/source/lobby/pkcs5_pbkdf2.cpp new file mode 100644 index 0000000000..c71a6d8513 --- /dev/null +++ b/source/lobby/pkcs5_pbkdf2.cpp @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2008 Damien Bergamini + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +// This file is based loosly off libutil/pkcs5_pbkdf2.c in OpenBSD. + +#include "pkcs5_pbkdf2.h" +#include "sha.h" + +static void hmac_sha256(unsigned char (&digest)[SHA_DIGEST_SIZE], + const unsigned char* text, size_t text_len, + const unsigned char* key, size_t key_len) +{ + SHA256 hash; + unsigned char tk[SHA_DIGEST_SIZE]; // temporary key incase we need to pad the key with zero unsigned chars + if (key_len > SHA_DIGEST_SIZE) + { + hash.update(key, key_len); + hash.finish(tk); + key = tk; + key_len = SHA_DIGEST_SIZE; + } + + unsigned char k_pad[SHA_DIGEST_SIZE]; + + memset(k_pad, 0, sizeof k_pad); + memcpy(k_pad, key, key_len); + for (int i = 0; i < SHA_DIGEST_SIZE; ++i) + k_pad[i] ^= 0x36; + hash.init(); + hash.update(k_pad, SHA_DIGEST_SIZE); + hash.update(text, text_len); + hash.finish(digest); + + + memset(k_pad, 0, sizeof k_pad); + memcpy(k_pad, key, key_len); + for (int i = 0; i < SHA_DIGEST_SIZE; ++i) + k_pad[i] ^= 0x5c; + + hash.init(); + hash.update(k_pad, SHA_DIGEST_SIZE); + hash.update(digest, SHA_DIGEST_SIZE); + hash.finish(digest); +} + + +int pbkdf2(unsigned char (&output)[SHA_DIGEST_SIZE], + const unsigned char* key, size_t key_len, + const unsigned char* salt, size_t salt_len, + unsigned rounds) +{ + unsigned char asalt[SHA_DIGEST_SIZE + 4], obuf[SHA_DIGEST_SIZE], d1[SHA_DIGEST_SIZE], d2[SHA_DIGEST_SIZE]; + + if (rounds < 1 || key_len == 0 || salt_len == 0) + return -1; + + if (salt_len > SHA_DIGEST_SIZE) salt_len = SHA_DIGEST_SIZE; // length cap for the salt + memset(asalt, 0, salt_len); + memcpy(asalt, salt, salt_len); + + for (unsigned count = 1; ; ++count) + { + asalt[salt_len + 0] = (count >> 24) & 0xff; + asalt[salt_len + 1] = (count >> 16) & 0xff; + asalt[salt_len + 2] = (count >> 8) & 0xff; + asalt[salt_len + 3] = count & 0xff; + hmac_sha256(d1, asalt, salt_len + 4, key, key_len); + memcpy(obuf, d1, SHA_DIGEST_SIZE); + + for (unsigned i = 1; i < rounds; i++) + { + hmac_sha256(d2, d1, SHA_DIGEST_SIZE, key, key_len); + memcpy(d1, d2, SHA_DIGEST_SIZE); + for (unsigned j = 0; j < SHA_DIGEST_SIZE; j++) + obuf[j] ^= d1[j]; + } + + memcpy(output, obuf, SHA_DIGEST_SIZE); + key += SHA_DIGEST_SIZE; + if (key_len < SHA_DIGEST_SIZE) + break; + key_len -= SHA_DIGEST_SIZE; + }; + return 0; +} + diff --git a/source/lobby/pkcs5_pbkdf2.h b/source/lobby/pkcs5_pbkdf2.h new file mode 100644 index 0000000000..77948ebcfd --- /dev/null +++ b/source/lobby/pkcs5_pbkdf2.h @@ -0,0 +1,44 @@ +/* Copyright (c) 2013 Wildfire Games + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef PKCS5_PBKD2_INCLUDED +#define PKCS5_PBKD2_INCLUDED + +#define SHA_DIGEST_SIZE 32 + + +/** + * Simple PBKDF2 implementation for hard to crack passwords + * @param output The output buffer for the digested hash + * @param key The initial key we want to hash + * @param key_len Length of the key in bytes + * @param salt The salt we use to iteratively hash the key. + * @param salt_len Length of the salt in bytes + * @param iterations Number of salting iterations + * @return 0 on success, -1 on error + */ +int pbkdf2(unsigned char (&output)[SHA_DIGEST_SIZE], + const unsigned char* key, size_t key_len, + const unsigned char* salt, size_t salt_len, + unsigned iterations); + +#endif // PKCS5_PBKD2_INCLUDED diff --git a/source/lobby/scripting/JSInterface_Lobby.cpp b/source/lobby/scripting/JSInterface_Lobby.cpp index c4b6cf9f90..b4a0a1bf96 100644 --- a/source/lobby/scripting/JSInterface_Lobby.cpp +++ b/source/lobby/scripting/JSInterface_Lobby.cpp @@ -22,6 +22,7 @@ #include "gui/GUIManager.h" #include "lib/utf8.h" #include "lobby/IXmppClient.h" +#include "lobby/pkcs5_pbkdf2.h" #include "lobby/sha.h" #include "scriptinterface/ScriptInterface.h" diff --git a/source/lobby/sha.cpp b/source/lobby/sha.cpp index 6fafdb15c2..819a693497 100644 --- a/source/lobby/sha.cpp +++ b/source/lobby/sha.cpp @@ -22,9 +22,6 @@ #include "sha.h" -#include -#include - #define GET_uint32(n,b,i) \ { \ (n) = ( (unsigned int) (b)[(i) ] << 24 ) \ @@ -266,98 +263,4 @@ void SHA256::finish(unsigned char (&digest)[32] ) PUT_uint32( state[6], digest, 24 ); PUT_uint32( state[7], digest, 28 ); } - - -/** - * Copyright (c) 2008 Damien Bergamini - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -// Next two functions are based very loosely off the functions in libutil/pkcs5_pbkdf2.c in OpenBSD. -static void hmac_sha256(unsigned char (&digest)[SHA_DIGEST_SIZE], - const unsigned char* text, size_t text_len, - const unsigned char* key, size_t key_len) -{ - SHA256 hash; - unsigned char tk[SHA_DIGEST_SIZE]; // temporary key incase we need to pad the key with zero unsigned chars - if (key_len > SHA_DIGEST_SIZE) - { - hash.update(key, key_len); - hash.finish(tk); - key = tk; - key_len = SHA_DIGEST_SIZE; - } - - unsigned char k_pad[SHA_DIGEST_SIZE]; - - memset(k_pad, 0, sizeof k_pad); - memcpy(k_pad, key, key_len); - for (int i = 0; i < SHA_DIGEST_SIZE; ++i) - k_pad[i] ^= 0x36; - hash.init(); - hash.update(k_pad, SHA_DIGEST_SIZE); - hash.update(text, text_len); - hash.finish(digest); - - - memset(k_pad, 0, sizeof k_pad); - memcpy(k_pad, key, key_len); - for (int i = 0; i < SHA_DIGEST_SIZE; ++i) - k_pad[i] ^= 0x5c; - - hash.init(); - hash.update(k_pad, SHA_DIGEST_SIZE); - hash.update(digest, SHA_DIGEST_SIZE); - hash.finish(digest); -} - - -int pbkdf2(unsigned char (&output)[SHA_DIGEST_SIZE], - const unsigned char* key, size_t key_len, - const unsigned char* salt, size_t salt_len, - unsigned rounds) -{ - unsigned char asalt[SHA_DIGEST_SIZE + 4], obuf[SHA_DIGEST_SIZE], d1[SHA_DIGEST_SIZE], d2[SHA_DIGEST_SIZE]; - - if (rounds < 1 || key_len == 0 || salt_len == 0) - return -1; - - if (salt_len > SHA_DIGEST_SIZE) salt_len = SHA_DIGEST_SIZE; // length cap for the salt - memset(asalt, 0, salt_len); - memcpy(asalt, salt, salt_len); - - for (unsigned count = 1; ; ++count) - { - asalt[salt_len + 0] = (count >> 24) & 0xff; - asalt[salt_len + 1] = (count >> 16) & 0xff; - asalt[salt_len + 2] = (count >> 8) & 0xff; - asalt[salt_len + 3] = count & 0xff; - hmac_sha256(d1, asalt, salt_len + 4, key, key_len); - memcpy(obuf, d1, SHA_DIGEST_SIZE); - - for (unsigned i = 1; i < rounds; i++) - { - hmac_sha256(d2, d1, SHA_DIGEST_SIZE, key, key_len); - memcpy(d1, d2, SHA_DIGEST_SIZE); - for (unsigned j = 0; j < SHA_DIGEST_SIZE; j++) - obuf[j] ^= d1[j]; - } - - memcpy(output, obuf, SHA_DIGEST_SIZE); - key += SHA_DIGEST_SIZE; - if (key_len < SHA_DIGEST_SIZE) - break; - key_len -= SHA_DIGEST_SIZE; - }; - return 0; -} + diff --git a/source/lobby/sha.h b/source/lobby/sha.h index abaece621b..436f6129d1 100644 --- a/source/lobby/sha.h +++ b/source/lobby/sha.h @@ -23,8 +23,6 @@ #ifndef SHA_INCLUDED #define SHA_INCLUDED -#define SHA_DIGEST_SIZE 32 - /** * Structure for performing SHA256 encryption on arbitrary data */ @@ -41,20 +39,4 @@ struct SHA256 void finish(unsigned char (&digest)[32]); }; - -/** - * Simple PBKDF2 implementation for hard to crack passwords - * @param output The output buffer for the digested hash - * @param key The initial key we want to hash - * @param key_len Length of the key in bytes - * @param salt The salt we use to iteratively hash the key. - * @param salt_len Length of the salt in bytes - * @param iterations Number of salting iterations - * @return 0 on success, -1 on error - */ -int pbkdf2(unsigned char (&output)[SHA_DIGEST_SIZE], - const unsigned char* key, size_t key_len, - const unsigned char* salt, size_t salt_len, - unsigned iterations); - #endif // SHA_INCLUDED