Open-Transactions  0.93.0-ge03d287
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
OTPassword.cpp
Go to the documentation of this file.
1 /************************************************************
2  *
3  * OTPassword.cpp
4  *
5  */
6 
7 /************************************************************
8  -----BEGIN PGP SIGNED MESSAGE-----
9  Hash: SHA1
10 
11  * OPEN TRANSACTIONS
12  *
13  * Financial Cryptography and Digital Cash
14  * Library, Protocol, API, Server, CLI, GUI
15  *
16  * -- Anonymous Numbered Accounts.
17  * -- Untraceable Digital Cash.
18  * -- Triple-Signed Receipts.
19  * -- Cheques, Vouchers, Transfers, Inboxes.
20  * -- Basket Currencies, Markets, Payment Plans.
21  * -- Signed, XML, Ricardian-style Contracts.
22  * -- Scripted smart contracts.
23  *
24  * Copyright (C) 2010-2013 by "Fellow Traveler" (A pseudonym)
25  *
26  * EMAIL:
28  *
29  * BITCOIN: 1NtTPVVjDsUfDWybS4BwvHpG2pdS9RnYyQ
30  *
31  * KEY FINGERPRINT (PGP Key in license file):
32  * 9DD5 90EB 9292 4B48 0484 7910 0308 00ED F951 BB8E
33  *
34  * OFFICIAL PROJECT WIKI(s):
35  * https://github.com/FellowTraveler/Moneychanger
36  * https://github.com/FellowTraveler/Open-Transactions/wiki
37  *
38  * WEBSITE:
39  * http://www.OpenTransactions.org/
40  *
41  * Components and licensing:
42  * -- Moneychanger..A Java client GUI.....LICENSE:.....GPLv3
43  * -- otlib.........A class library.......LICENSE:...LAGPLv3
44  * -- otapi.........A client API..........LICENSE:...LAGPLv3
45  * -- opentxs/ot....Command-line client...LICENSE:...LAGPLv3
46  * -- otserver......Server Application....LICENSE:....AGPLv3
47  * Github.com/FellowTraveler/Open-Transactions/wiki/Components
48  *
49  * All of the above OT components were designed and written by
50  * Fellow Traveler, with the exception of Moneychanger, which
51  * was contracted out to Vicky C ([email protected]).
52  * The open-source community has since actively contributed.
53  *
54  * -----------------------------------------------------
55  *
56  * LICENSE:
57  * This program is free software: you can redistribute it
58  * and/or modify it under the terms of the GNU Affero
59  * General Public License as published by the Free Software
60  * Foundation, either version 3 of the License, or (at your
61  * option) any later version.
62  *
63  * ADDITIONAL PERMISSION under the GNU Affero GPL version 3
64  * section 7: (This paragraph applies only to the LAGPLv3
65  * components listed above.) If you modify this Program, or
66  * any covered work, by linking or combining it with other
67  * code, such other code is not for that reason alone subject
68  * to any of the requirements of the GNU Affero GPL version 3.
69  * (==> This means if you are only using the OT API, then you
70  * don't have to open-source your code--only your changes to
71  * Open-Transactions itself must be open source. Similar to
72  * LGPLv3, except it applies to software-as-a-service, not
73  * just to distributing binaries.)
74  *
75  * Extra WAIVER for OpenSSL, Lucre, and all other libraries
76  * used by Open Transactions: This program is released under
77  * the AGPL with the additional exemption that compiling,
78  * linking, and/or using OpenSSL is allowed. The same is true
79  * for any other open source libraries included in this
80  * project: complete waiver from the AGPL is hereby granted to
81  * compile, link, and/or use them with Open-Transactions,
82  * according to their own terms, as long as the rest of the
83  * Open-Transactions terms remain respected, with regard to
84  * the Open-Transactions code itself.
85  *
86  * Lucre License:
87  * This code is also "dual-license", meaning that Ben Lau-
88  * rie's license must also be included and respected, since
89  * the code for Lucre is also included with Open Transactions.
90  * See Open-Transactions/src/otlib/lucre/LUCRE_LICENSE.txt
91  * The Laurie requirements are light, but if there is any
92  * problem with his license, simply remove the Lucre code.
93  * Although there are no other blind token algorithms in Open
94  * Transactions (yet. credlib is coming), the other functions
95  * will continue to operate.
96  * See Lucre on Github: https://github.com/benlaurie/lucre
97  * -----------------------------------------------------
98  * You should have received a copy of the GNU Affero General
99  * Public License along with this program. If not, see:
100  * http://www.gnu.org/licenses/
101  *
102  * If you would like to use this software outside of the free
103  * software license, please contact FellowTraveler.
104  * (Unfortunately many will run anonymously and untraceably,
105  * so who could really stop them?)
106  *
107  * DISCLAIMER:
108  * This program is distributed in the hope that it will be
109  * useful, but WITHOUT ANY WARRANTY; without even the implied
110  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
111  * PURPOSE. See the GNU Affero General Public License for
112  * more details.
113 
114  -----BEGIN PGP SIGNATURE-----
115  Version: GnuPG v1.4.9 (Darwin)
116 
117  iQIcBAEBAgAGBQJRSsfJAAoJEAMIAO35UbuOQT8P/RJbka8etf7wbxdHQNAY+2cC
118  vDf8J3X8VI+pwMqv6wgTVy17venMZJa4I4ikXD/MRyWV1XbTG0mBXk/7AZk7Rexk
119  KTvL/U1kWiez6+8XXLye+k2JNM6v7eej8xMrqEcO0ZArh/DsLoIn1y8p8qjBI7+m
120  aE7lhstDiD0z8mwRRLKFLN2IH5rAFaZZUvj5ERJaoYUKdn4c+RcQVei2YOl4T0FU
121  LWND3YLoH8naqJXkaOKEN4UfJINCwxhe5Ke9wyfLWLUO7NamRkWD2T7CJ0xocnD1
122  sjAzlVGNgaFDRflfIF4QhBx1Ddl6wwhJfw+d08bjqblSq8aXDkmFA7HeunSFKkdn
123  oIEOEgyj+veuOMRJC5pnBJ9vV+7qRdDKQWaCKotynt4sWJDGQ9kWGWm74SsNaduN
124  TPMyr9kNmGsfR69Q2Zq/FLcLX/j8ESxU+HYUB4vaARw2xEOu2xwDDv6jt0j3Vqsg
125  x7rWv4S/Eh18FDNDkVRChiNoOIilLYLL6c38uMf1pnItBuxP3uhgY6COm59kVaRh
126  nyGTYCDYD2TK+fI9o89F1297uDCwEJ62U0Q7iTDp5QuXCoxkPfv8/kX6lS6T3y9G
127  M9mqIoLbIQ1EDntFv7/t6fUTS2+46uCrdZWbQ5RjYXdrzjij02nDmJAm2BngnZvd
128  kamH0Y/n11lCvo1oQxM+
129  =uSzz
130  -----END PGP SIGNATURE-----
131  **************************************************************/
132 
133 #include "stdafx.hpp"
134 
135 #include "crypto/OTPassword.hpp"
136 
137 #include "crypto/OTCrypto.hpp"
138 #include "OTLog.hpp"
139 
140 // For SecureZeroMemory
141 #ifdef _WIN32
142 #else // not _WIN32
143 
144 // for mlock and munlock
145 #include <sys/types.h>
146 #include <sys/mman.h>
147 #include <limits.h>
148 
149 #ifndef PAGESIZE
150 #include <unistd.h>
151 #define PAGESIZE sysconf(_SC_PAGESIZE)
152 #endif
153 
154 // FT: Credit to the Bitcoin team for the mlock / munlock defines.
155 
156 #define mlock(a, b) \
157  mlock(((void*)(((size_t)(a)) & (~((PAGESIZE)-1)))), \
158  (((((size_t)(a)) + (b)-1) | ((PAGESIZE)-1)) + 1) - \
159  (((size_t)(a)) & (~((PAGESIZE)-1))))
160 #define munlock(a, b) \
161  munlock(((void*)(((size_t)(a)) & (~((PAGESIZE)-1)))), \
162  (((((size_t)(a)) + (b)-1) | ((PAGESIZE)-1)) + 1) - \
163  (((size_t)(a)) & (~((PAGESIZE)-1))))
164 #endif
165 
166 namespace opentxs
167 {
168 
169 // For everything but Windows:
170 //
171 #ifndef _WIN32
172 extern "C" void* ot_secure_memset(void* v, uint8_t c, uint32_t n);
173 
174 // This function securely overwrites the contents of a memory buffer
175 // (which can otherwise be optimized out by an overzealous compiler...)
176 //
177 void* ot_secure_memset(void* v, uint8_t c, uint32_t n)
178 {
179  OT_ASSERT((nullptr != v) && (n > 0));
180 
181  volatile uint8_t* p = static_cast<volatile uint8_t*>(v);
182  while (n--) *p++ = c;
183 
184  return v;
185 }
186 #endif // _WIN32
187 
188 // TODO, security: Generate a session key, and encrypt the password string to
189 // that key whenever setting it,
190 // and decrypt it using that key whenever getting it. Also make sure to use the
191 // lock / unlock functions
192 // at that time (below). Also change so that the contents are dynamically
193 // allocated.
194 // NOTE: Given that OTSymmetricKey works with OTPassword, this is a bit circular
195 // in logic. Therefore might
196 // need to add a function to OTEnvelope so that it takes a const char * instead
197 // of an OTPassword, in order
198 // to handle this specific case! Might also need to duplicate some code between
199 // OTSymmetricKey and OTPassword
200 // in order to make sure both have the same protections. I'll see if there's a
201 // way to do this without duplication,
202 // as I get deeper into it.
203 
204 /*
205 #ifdef _WIN64
206  //define something for Windows (64-bit)
207 #elif _WIN32
208  //define something for Windows (32-bit)
209 #elif __APPLE__
210  #include "TargetConditionals.h"
211  #ifdef TARGET_OS_IPHONE
212  // iOS
213  #elif TARGET_IPHONE_SIMULATOR
214  // iOS Simulator
215  #elif TARGET_OS_MAC
216  // Other kinds of Mac OS
217  #else
218  // Unsupported platform
219  #endif
220 #elif __linux
221  // linux
222 #elif __unix // all unices not caught above
223  // Unix
224 #elif __posix
225  // POSIX
226 #endif
227  */
228 
229 // THE PURPOSE OF LOCKING A PAGE:
230 //
231 // "So that it won't get swapped to disk, where the secret
232 // could be recovered maliciously from the swap file."
233 //
234 bool ot_lockPage(void* addr, size_t len)
235 {
236 #ifdef _WIN32
237 // return VirtualLock(addr, len);
238 #elif defined(PREDEF_PLATFORM_UNIX)
239  static bool bWarned = false;
240  if (mlock(addr, len) && !bWarned) {
241  bWarned = true;
242  otErr << "ot_lockPage: WARNING: unable to lock memory. \n"
243  " (Passwords / secret keys may be swapped to disk!)\n";
244  }
245  return true;
246 #else
247  OT_FAIL_MSG("ASSERT: ot_lockPage unable to lock memory.");
248 #endif
249  return false;
250 }
251 
252 // TODO: Note: may need to add directives here so that mlock and munlock are
253 // not
254 // used except where the user is running as a privileged process. (Because that
255 // may be the only way we CAN use those functions...)
256 
257 bool ot_unlockPage(void* addr, size_t len)
258 {
259 #ifdef _WIN32
260 // return VirtualUnlock(addr, len);
261 #elif defined(PREDEF_PLATFORM_UNIX)
262  static bool bWarned = false;
263  if (munlock(addr, len) && !bWarned) {
264  bWarned = true;
265  otErr << "ot_unlockPage: WARNING: unable to unlock memory used for "
266  "storing secrets.\n";
267  }
268  return true;
269 #else
270  OT_FAIL_MSG("ASSERT: ot_unlockPage unable to unlock secret memory.");
271 #endif
272  return false;
273 }
274 
275 // PURPOSE OF ZERO'ING MEMORY:
276 //
277 // So the secret is not stored in memory any longer than absolutely necessary.
278 // Once it has been used, we want to wipe it from memory ASAP. (The least amount
279 // of time spent in memory, the better.)
280 
282 {
283  size_ = 0;
284 
285  OTPassword::zeroMemory(static_cast<void*>(&(data_[0])),
286  static_cast<uint32_t>(getBlockSize()));
287 
288 //
289 #ifndef _WIN32
290  // UNLOCK the page, now that we're AFTER the point where
291  // the memory was safely ZERO'd out.
292  //
293  if (isPageLocked_) {
294  if (ot_unlockPage(static_cast<void*>(&(data_[0])),
295  static_cast<uint32_t>(getBlockSize()))) {
296  isPageLocked_ = false;
297  }
298  else
299  otErr << "OTPassword::zeroMemory: Error: Memory page was locked, "
300  "but then failed to unlock it.\n";
301  }
302 #endif
303 }
304 
305 // static
306 void OTPassword::zeroMemory(void* vMemory, uint32_t theSize)
307 {
308  // OT_ASSERT_MSG((nullptr != vMemory) && (theSize >
309  // 0),"OTPassword::zeroMemory: ASSERT: vMemory is nullptr or theSize is
310  // 0.");
311 
312  if ((nullptr != vMemory) && (theSize > 0)) {
313  uint8_t* szMemory = static_cast<uint8_t*>(vMemory);
314  OTPassword::zeroMemory(szMemory, theSize);
315  }
316 }
317 
318 // static
319 void OTPassword::zeroMemory(uint8_t* szMemory, uint32_t theSize)
320 {
321 #ifdef _WIN32
322 
323  //
324  SecureZeroMemory(szMemory, theSize);
325 
326 // NOTE: Both SecureZeroMemory, and the pragma solution commented-out below,
327 // are acceptable for Windows. I put both here for my notes.
328 //
329 //#pragma optimize("", off)
330 // memset(szMemory, 0, theSize);
331 //#pragma optimize("", on)
332 
333 // Dr. UNIX, I presume? So, we meet again...
334 #else
335  ot_secure_memset(szMemory, static_cast<uint8_t>(0), theSize);
336 #endif
337 }
338 
339 /* WINDOWS:
340  errno_t memcpy_s(void* dest,
341  size_t numberOfElements,
342  const
343  void * src,
344  size_t count
345  );
346 
347  FT: Apparently numberOfElements is similar to strcpy_s (where it's the maximum
348  size of destination buffer.)
349  "numberOfElements is the Maximum number of characters destination string can
350  accomodate including the nullptr character"
351  (Then count is the actual size being copied.)
352  */
353 // UNIX:
354 // void * memcpy(void* restrict s1, const void* restrict s2, size_t n);
355 //
356 // static
357 void* OTPassword::safe_memcpy(void* dest, uint32_t dest_size, const void* src,
358  uint32_t src_length,
359  bool bZeroSource) // if true, sets the
360  // source buffer to
361  // zero after copying
362  // is done.
363 {
364  // Make sure they aren't null.
365  OT_ASSERT(nullptr != dest);
366  OT_ASSERT(nullptr != src);
367 
368  // Make sure they aren't the same pointer.
369  OT_ASSERT(src != dest);
370 
371  // Make sure it will fit.
372  OT_ASSERT_MSG(src_length <= dest_size,
373  "ASSERT: safe_memcpy: destination buffer too small.\n");
374 
375  // Make sure they don't overlap.
376  // First assert does the beginning of the string, makes sure it's not within
377  // the bounds of the destination
378  // string. Second assert does the same thing for the end of the string.
379  // Finally a third is needed to make sure
380  // we're not in a situation where the beginning is less than the dest
381  // beginning, yet the end is also more than
382  // the dest ending!
383  //
385  false ==
386  ((static_cast<const uint8_t*>(src) > static_cast<uint8_t*>(dest)) &&
387  (static_cast<const uint8_t*>(src) <
388  (static_cast<uint8_t*>(dest) + dest_size))),
389  "ASSERT: safe_memcpy: Unexpected memory overlap, start of src.\n");
391  false == (((static_cast<const uint8_t*>(src) + src_length) >
392  static_cast<uint8_t*>(dest)) &&
393  ((static_cast<const uint8_t*>(src) + src_length) <
394  (static_cast<uint8_t*>(dest) + dest_size))),
395  "ASSERT: safe_memcpy: Unexpected memory overlap, end of src.\n");
396  OT_ASSERT(false == ((static_cast<const uint8_t*>(src) <=
397  static_cast<uint8_t*>(dest)) &&
398  ((static_cast<const uint8_t*>(src) + src_length) >=
399  (static_cast<uint8_t*>(dest) + dest_size))));
400 
401 #ifdef _WIN32
402  bool bSuccess = (0 == memcpy_s(dest, static_cast<size_t>(dest_size), src,
403  static_cast<size_t>(src_length)));
404 #else
405  bool bSuccess =
406  (memcpy(dest, src, static_cast<size_t>(src_length)) == dest);
407 #endif
408 
409  if (bSuccess) {
410  if (bZeroSource) {
411  OTPassword::zeroMemory(const_cast<void*>(src), src_length);
412  }
413 
414  return dest;
415  }
416 
417  return nullptr;
418 }
419 
420 // OTPassword thePass; will create a text password.
421 // But use the below function if you want one that has
422 // a text buffer of size (versus a 0 size.) This is for
423 // cases where you need the buffer to pre-exist so that
424 // some other function can populate that buffer directly.
425 // (Such as the OpenSSL password callback...)
426 // CALLER IS RESPONSIBLE TO DELETE.
427 //
428 // static
430 {
431  // Caller MUST delete!
432 
433  char throwaway_text[OT_DEFAULT_BLOCKSIZE];
434  for (int32_t tt = 0; tt < OT_DEFAULT_BLOCKSIZE; ++tt) {
435  throwaway_text[tt] = 'A'; // todo optimization...
436  }
437  throwaway_text[OT_DEFAULT_BLOCKSIZE - 1] = '\0';
438  // We don't use the above memory, except to force OTPassword to create
439  // itself
440  // at a certain password size, so we can pass that buffer and size on to any
441  // C-style function that needs them to "already exist."
442  //
443  OTPassword* pPassUserInput = new OTPassword(
444  &(throwaway_text[0]), OT_DEFAULT_BLOCKSIZE - 1); // text mode.
445  OT_ASSERT_MSG(nullptr != pPassUserInput,
446  "OTPassword::CreateTextBuffer: ASSERT: OTPassword * "
447  "pPassUserInput = new OTPassword(&(throwaway_text[0]), "
448  "OT_DEFAULT_BLOCKSIZE-1);");
449  // Below this point, pPassUserInput must be returned, or deleted. (Or it
450  // will leak.)
451 
452  return pPassUserInput;
453 }
454 
456  : size_(0)
457  , isText_(true)
458  , isBinary_(false)
459  , isPageLocked_(false)
460  , blockSize_(theBlockSize)
461 {
462  data_[0] = '\0';
463  setPassword_uint8(reinterpret_cast<const uint8_t*>(""), 0);
464 }
465 
467 {
468  if (rhs.isPassword()) {
470  }
471  else if (rhs.isMemory()) {
473  }
474 
475  return *this;
476 }
477 
479  : size_(0)
480  , isText_(rhs.isPassword())
481  , isBinary_(rhs.isMemory())
482  , isPageLocked_(false)
483  , blockSize_(
484  rhs.blockSize_) // The buffer has this size+1 as its static size.
485 {
486  if (isText_) {
487  data_[0] = '\0';
489  }
490  else if (isBinary_) {
492  }
493 }
494 
495 OTPassword::OTPassword(const char* szInput, uint32_t nInputSize,
496  OTPassword::BlockSize theBlockSize)
497  : size_(0)
498  , isText_(true)
499  , isBinary_(false)
500  , isPageLocked_(false)
501  , blockSize_(theBlockSize) // The buffer has this size+1 as its static size.
502 {
503  data_[0] = '\0';
504 
505  setPassword_uint8(reinterpret_cast<const uint8_t*>(szInput), nInputSize);
506 }
507 
508 OTPassword::OTPassword(const uint8_t* szInput, uint32_t nInputSize,
509  OTPassword::BlockSize theBlockSize)
510  : size_(0)
511  , isText_(true)
512  , isBinary_(false)
513  , isPageLocked_(false)
514  , blockSize_(theBlockSize) // The buffer has this size+1 as its static size.
515 {
516  data_[0] = '\0';
517 
518  setPassword_uint8(szInput, nInputSize);
519 }
520 
521 OTPassword::OTPassword(const void* vInput, uint32_t nInputSize,
522  OTPassword::BlockSize theBlockSize)
523  : size_(0)
524  , isText_(false)
525  , isBinary_(true)
526  , isPageLocked_(false)
527  , blockSize_(theBlockSize) // The buffer has this size+1 as its static size.
528 {
529  setMemory(vInput, nInputSize);
530 }
531 
533 {
534  if (size_ > 0) zeroMemory();
535 }
536 
538 {
539  return isText_;
540 }
541 
543 {
544  return isBinary_;
545 }
546 
547 const char* OTPassword::getPassword() const // asserts if isText_ is false.
548 {
549  return reinterpret_cast<const char*>(getPassword_uint8());
550 }
551 
552 // getPassword returns "" if empty, otherwise returns the password.
553 //
554 const uint8_t* OTPassword::getPassword_uint8() const
555 {
556  OT_ASSERT(isText_);
557  return (size_ <= 0) ? reinterpret_cast<const uint8_t*>("") : &(data_[0]);
558 }
559 
561 {
562  OT_ASSERT(isText_);
563  return (size_ <= 0)
564  ? nullptr
565  : static_cast<uint8_t*>(static_cast<void*>(&(data_[0])));
566 }
567 
569 {
570  OT_ASSERT(isText_);
571  return (size_ <= 0) ? nullptr
572  : static_cast<char*>(static_cast<void*>(&(data_[0])));
573 }
574 
575 // getMemory returns nullptr if empty, otherwise returns the password.
576 //
577 const void* OTPassword::getMemory() const
578 {
579  return reinterpret_cast<const void*>(getMemory_uint8());
580 }
581 
582 const uint8_t* OTPassword::getMemory_uint8() const
583 {
584  OT_ASSERT(isBinary_);
585  return (size_ <= 0) ? nullptr : static_cast<const uint8_t*>(&(data_[0]));
586 }
587 
588 // getMemoryWritable returns nullptr if empty, otherwise returns the password.
590 {
591  OT_ASSERT(isBinary_);
592  return (size_ <= 0) ? nullptr : static_cast<void*>(&(data_[0]));
593 }
594 
595 uint32_t OTPassword::getBlockSize() const
596 {
597  uint32_t nReturn = 0;
598 
599  switch (blockSize_) {
601  nReturn = static_cast<uint32_t>(OT_DEFAULT_BLOCKSIZE);
602  break;
604  nReturn = static_cast<uint32_t>(OT_LARGE_BLOCKSIZE);
605  break;
606  default:
607  break;
608  }
609 
610  return nReturn;
611 }
612 
614 {
615  OT_ASSERT(isText_);
616  return size_;
617 }
618 
620 {
621  OT_ASSERT(isBinary_);
622  return size_;
623 }
624 
625 bool OTPassword::addChar(uint8_t theChar)
626 {
628  if (getPasswordSize() < getBlockSize()) {
629  data_[size_] = theChar;
630  ++size_;
631  data_[size_] = '\0';
632  return true;
633  }
634  return false;
635 }
636 
638 {
639  OT_ASSERT(isPassword() || isMemory());
640  OT_ASSERT(rhs.isPassword() || rhs.isMemory());
641 
642  if (isPassword() && !rhs.isPassword()) return false;
643  if (isMemory() && !rhs.isMemory()) return false;
644 
645  const uint32_t nThisSize =
647  const uint32_t nRhsSize =
648  rhs.isPassword() ? rhs.getPasswordSize() : rhs.getMemorySize();
649 
650  if (nThisSize != nRhsSize) return false;
651 
652  if (0 ==
654  rhs.isPassword() ? rhs.getPassword_uint8()
655  : rhs.getMemory_uint8(),
656  rhs.isPassword() ? rhs.getPasswordSize() : rhs.getMemorySize()))
657  return true;
658 
659  return false;
660 }
661 
662 // Returns size of password (in case truncation is necessary.)
663 // Returns -1 in case of error.
664 //
665 int32_t OTPassword::setPassword(const char* szInput, int32_t nInputSize)
666 {
667  return static_cast<int32_t>(
668  setPassword_uint8(reinterpret_cast<const uint8_t*>(szInput),
669  static_cast<uint32_t>(nInputSize)));
670 }
671 
672 // This adds a null terminator.
673 //
674 int32_t OTPassword::setPassword_uint8(const uint8_t* szInput,
675  uint32_t nInputSize)
676 {
677  OT_ASSERT(nullptr != szInput);
678 
679  // cppcheck-suppress variableScope
680  const char* szFunc = "OTPassword::setPassword";
681 
682  // Wipe whatever was in there before.
683  //
684  if (size_ > 0) zeroMemory();
685 
686  isBinary_ = false;
687  isText_ = true;
688 
689  if (0 == nInputSize) return 0;
690 
691  // Make sure no input size is larger than our block size
692  //
693  if (nInputSize > getBlockSize())
694  nInputSize = getBlockSize(); // Truncated password beyond max size.
695 
696  // The szInput string passed into this function should never
697  // be a different size than what is passed in. For example it shouldn't
698  // be SMALLER than what the user claims either. If it is, we error out.
699  //
700  if (OTString::safe_strlen(reinterpret_cast<const char*>(szInput),
701  static_cast<size_t>(nInputSize)) <
702  static_cast<size_t>(nInputSize)) {
703  otErr
704  << szFunc
705  << ": ERROR: string length of szInput did not match nInputSize.\n";
706  return (-1);
707  }
708 
709 #ifndef _WIN32
710 
711  //
712  // Lock the memory page, before we copy the data over.
713  // (If it's not already locked, which I doubt it will be.)
714  //
715  // it won't be locked already, since we just zero'd it
716  // (above.) But I check this anyway...
717  if (!isPageLocked_) {
718  if (ot_lockPage(static_cast<void*>(&(data_[0])), getBlockSize())) {
719  isPageLocked_ = true;
720  }
721  else {
722  otErr << szFunc
723  << ": Error: Failed attempting to lock memory page.\n";
724  }
725  }
726 #endif
727 
728 #ifdef _WIN32
729  strncpy_s(reinterpret_cast<char*>(data_), (1 + nInputSize),
730  reinterpret_cast<const char*>(szInput), nInputSize);
731 #else
732  strncpy(reinterpret_cast<char*>(data_),
733  reinterpret_cast<const char*>(szInput), nInputSize);
734 #endif
735 
736  // force a null terminator in the 129th byte (at index 128.)
737  // (Or at the 6th byte (at index 5), if the size is 5 bytes int64_t.)
738  //
739  data_[nInputSize] = '\0';
740  size_ = nInputSize;
741 
742  return size_;
743 }
744 
745 // OTPassword::SetSize (Low-level)
746 //
747 // There are certain weird cases, like in OTSymmetricKey::GetPassphraseFromUser,
748 // where we set the password using the getPassword_writable, and it's properly
749 // null-terminated, yet this instance still doesn't know its actual size (even
750 // though
751 // the size is known.) Therefore I added this call in order to set the size in
752 // those odd cases where it's necessary. That being said, YOU should normally
753 // NEVER
754 // need to use this function, so just pretend it doesn't exist.
755 //
756 // This adds a null terminator, IF we're in text mode (not binary mode.)
757 //
758 bool OTPassword::SetSize(uint32_t uSize)
759 {
760  if (isBinary_) {
761  if (uSize > getBlockSize())
762  uSize = getBlockSize(); // Truncated password beyond max size.
763  size_ = uSize;
764  return true;
765  }
766  else if (isText_) {
767  // Cannot be as much as the blocksize,
768  // because no room for null-terminator.
769  if (uSize >= getBlockSize()) {
770  uSize = getBlockSize() - 1; // Truncated password to blocksize-1.
771  }
772  // The actual null-terminator.
773  data_[uSize] = '\0';
774  // If size is 3, the terminator is at
775  size_ = uSize;
776  // data_[3] (which is the 4th byte.)
777  return true;
778  }
779  otErr << __FUNCTION__ << ": Error: isBinary_ and isText_ are both "
780  "false. (Should never happen.)\n";
781  return false;
782 }
783 
784 // static
785 bool OTPassword::randomizePassword(char* szDestination, uint32_t nNewSize)
786 {
788  reinterpret_cast<uint8_t*>(szDestination), nNewSize);
789 }
790 
791 // static
792 bool OTPassword::randomizePassword_uint8(uint8_t* szDestination,
793  uint32_t nNewSize)
794 {
795  OT_ASSERT(nullptr != szDestination);
796  OT_ASSERT(nNewSize > 0);
797 
798  // const char * szFunc = "OTPassword::randomizePassword(static)";
799 
800  if (OTPassword::randomizeMemory_uint8(szDestination, nNewSize)) {
801 
802  // This loop converts an array of binary bytes into the
803  // same array, where each byte is translated to a byte
804  // between the values of 33 and 122 (visible ASCII.)
805  //
806  for (uint32_t i = 0; i < nNewSize; ++i) {
807  uint8_t temp = (((szDestination[i]) % 89) + 33);
808  szDestination[i] = temp;
809  }
810 
811  // Add the nullptr terminator...
812  //
813  szDestination[nNewSize - 1] = '\0';
814 
815  return true;
816  }
817  return false;
818 }
819 
820 // Returns size of memory (in case truncation is necessary.)
821 // Returns -1 in case of error.
822 //
823 int32_t OTPassword::randomizePassword(uint32_t nNewSize)
824 {
825  uint32_t nSize = nNewSize;
826 
827  // Wipe whatever was in there before.
828  //
829  if (size_ > 0) zeroMemory();
830 
831  isBinary_ = false;
832  isText_ = true;
833 
834  if (0 == nSize) return 0;
835 
836  // Make sure no input size is larger than our block size
837  //
838  if (nSize > getBlockSize())
839  nSize = getBlockSize(); // Truncated password beyond max size.
840 #ifndef _WIN32
841  //
842  // Lock the memory page, before we randomize 'size bytes' of the data.
843  // (If it's not already locked, which I doubt it will be.)
844  //
845  if (!isPageLocked_) // it won't be locked already, since we just zero'd it
846  // (above.) But I check this anyway...
847  {
848  if (ot_lockPage(static_cast<void*>(&(data_[0])), getBlockSize())) {
849  isPageLocked_ = true;
850  }
851  else {
852  otErr << __FUNCTION__
853  << ": Error: Failed attempting to lock memory page.\n";
854  }
855  }
856 #endif
857 
858  //
859  if (!OTPassword::randomizePassword_uint8(&(data_[0]),
860  static_cast<int32_t>(nSize + 1))) {
861  // randomizeMemory (above) already logs, so I'm not logging again twice
862  // here.
863  //
864  zeroMemory();
865  return -1;
866  }
867 
868  size_ = nSize;
869 
870  return size_;
871 }
872 
873 // static
874 bool OTPassword::randomizeMemory(void* szDestination, uint32_t nNewSize)
875 {
877  reinterpret_cast<uint8_t*>(szDestination), nNewSize);
878 }
879 
880 // static
881 bool OTPassword::randomizeMemory_uint8(uint8_t* szDestination,
882  uint32_t nNewSize)
883 {
884  return OTCrypto::It()->RandomizeMemory(szDestination, nNewSize);
885 }
886 
887 // Returns size of memory (in case truncation is necessary.)
888 // Returns -1 in case of error.
889 //
890 int32_t OTPassword::randomizeMemory(uint32_t nNewSize)
891 {
892  uint32_t nSize = nNewSize;
893 
894  // Wipe whatever was in there before.
895  //
896  if (size_ > 0) zeroMemory();
897 
898  isBinary_ = true;
899  isText_ = false;
900 
901  if (0 == nSize) return 0;
902 
903  // Make sure no input size is larger than our block size
904  //
905  if (nSize > getBlockSize())
906  nSize = getBlockSize(); // Truncated password beyond max size.
907 
908 #ifndef _WIN32
909  //
910  // Lock the memory page, before we randomize 'size bytes' of the data.
911  // (If it's not already locked, which I doubt it will be.)
912  //
913  if (!isPageLocked_) // it won't be locked already, since we just zero'd it
914  // (above.) But I check this anyway...
915  {
916  if (ot_lockPage(static_cast<void*>(&(data_[0])), getBlockSize())) {
917  isPageLocked_ = true;
918  }
919  else {
920  otErr << __FUNCTION__
921  << ": Error: Failed attempting to lock memory page.\n";
922  }
923  }
924 #endif
925 
926  //
927  if (!OTPassword::randomizeMemory_uint8(&(data_[0]), nSize)) {
928  // randomizeMemory (above) already logs, so I'm not logging again twice
929  // here.
930  //
931  zeroMemory();
932  return -1;
933  }
934 
935  size_ = nSize;
936 
937  return size_;
938 }
939 
940 // (FYI, truncates if nAppendSize + getPasswordSize() is larger than
941 // getBlockSize.)
942 // Returns number of bytes appended, or -1 for error.
943 //
944 int32_t OTPassword::addMemory(const void* vAppend, uint32_t nAppendSize)
945 {
946  OT_ASSERT(nullptr != vAppend);
947 
948  // const char * szFunc = "OTPassword::addMemory";
949 
950  if (0 == nAppendSize) return 0;
951 
952  // If I'm currently at a 0 size, then call setMemory instead.
953  //
954  if (size_ == 0) return setMemory(vAppend, nAppendSize);
955  //
956  // By this point, I know I already have some memory allocated,
957  // and I'm actually appending some other memory onto the end of it.
958  //
959  // Should already be set from the above setMemory call.
960  OT_ASSERT(isBinary_);
961 
962  // Make sure total new size isn't larger than our block size
963  //
964  if ((nAppendSize + size_) > getBlockSize()) {
965  // Truncated password beyond max size.
966  nAppendSize = (getBlockSize() - size_);
967  }
968  // OT_ASSERT(nAppendSize >= 0);
969 
970  if (0 == nAppendSize) return 0;
971 
972  // By this point, I know nAppendSize is larger than 0, AND that appending it
973  // onto the
974  // existing memory of this object will not exceed the total allowed block
975  // size.
976  //
977  // Because we use setMemory when empty, and only use addMemory when we KNOW
978  // something
979  // is already there, therefore we know the page is already locked, so no
980  // need to go
981  // trying to lock it again.
982 
984  static_cast<void*>(&(data_[size_])),
985  static_cast<uint32_t>(nAppendSize), // dest size is based on the source
986  // size, but guaranteed to be >0 and
987  // <=getBlockSize
988  vAppend, static_cast<uint32_t>(nAppendSize)); // Since dest size is
989  // known to be src size or
990  // less (and >0) we use it
991  // as src size. (We may
992  // have truncated... and
993  // we certainly don't want
994  // to copy beyond our own
995  // truncation.)
996 
997  size_ += nAppendSize;
998 
999  return nAppendSize;
1000 }
1001 
1002 // Returns size of memory (in case truncation is necessary.)
1003 // Returns -1 in case of error.
1004 //
1005 int32_t OTPassword::setMemory(const void* vInput, uint32_t nInputSize)
1006 {
1007  OT_ASSERT(nullptr != vInput);
1008 
1009  // Wipe whatever was in there before.
1010  //
1011  if (size_ > 0) zeroMemory();
1012 
1013  isBinary_ = true;
1014  isText_ = false;
1015 
1016  if (0 == nInputSize) return 0;
1017 
1018  // Make sure no input size is larger than our block size
1019  //
1020  if (nInputSize > getBlockSize())
1021  nInputSize = getBlockSize(); // Truncated password beyond max size.
1022 
1023 #ifndef _WIN32
1024  //
1025  // Lock the memory page, before we copy the data over.
1026  // (If it's not already locked, which I doubt it will be.)
1027  //
1028  if (!isPageLocked_) // it won't be locked already, since we just zero'd it
1029  // (above.) But I check this anyway...
1030  {
1031  if (ot_lockPage(static_cast<void*>(&(data_[0])), getBlockSize())) {
1032  isPageLocked_ = true;
1033  }
1034  else {
1035  otErr << __FUNCTION__
1036  << ": Error: Failed attempting to lock memory page.\n";
1037  }
1038  }
1039 #endif
1040 
1041  OTPassword::safe_memcpy(static_cast<void*>(&(data_[0])),
1042  // dest size is based on the source
1043  // size, but guaranteed to be >0 and
1044  // <=getBlockSize
1045  static_cast<uint32_t>(nInputSize),
1046  // Since dest size is known
1047  // to be src size or less
1048  // (and >0) we use it as src
1049  // size. (We may have
1050  // truncated... and we
1051  // certainly don't want to
1052  // copy beyond our own
1053  // truncation.)
1054  vInput, static_cast<uint32_t>(nInputSize));
1055 
1056  size_ = nInputSize;
1057  return size_;
1058 }
1059 
1060 } // namespace opentxs
EXPORT const uint8_t * getMemory_uint8() const
Definition: OTPassword.cpp:582
static EXPORT OTCrypto * It()
Definition: OTCrypto.cpp:630
virtual bool RandomizeMemory(uint8_t *szDestination, uint32_t nNewSize) const =0
EXPORT uint32_t getMemorySize() const
Definition: OTPassword.cpp:619
EXPORT OTPassword(BlockSize blockSize=DEFAULT_SIZE)
Definition: OTPassword.cpp:455
static EXPORT bool randomizePassword_uint8(uint8_t *destination, uint32_t size)
Definition: OTPassword.cpp:792
EXPORT uint8_t * getPasswordWritable()
Definition: OTPassword.cpp:560
EXPORT void zeroMemory()
Definition: OTPassword.cpp:281
EXPORT int32_t addMemory(const void *append, uint32_t size)
Definition: OTPassword.cpp:944
bool ot_unlockPage(void *addr, size_t len)
Definition: OTPassword.cpp:257
EXPORT bool isPassword() const
Definition: OTPassword.cpp:537
#define mlock(a, b)
Definition: OTPassword.cpp:156
EXPORT char * getPasswordWritable_char()
Definition: OTPassword.cpp:568
EXPORT const void * getMemory() const
Definition: OTPassword.cpp:577
EXPORT int32_t setMemory(const void *input, uint32_t size)
EXPORT int32_t setPassword(const char *input, int32_t size)
Definition: OTPassword.cpp:665
EXPORT bool addChar(uint8_t c)
Definition: OTPassword.cpp:625
static EXPORT bool randomizeMemory_uint8(uint8_t *destination, uint32_t size)
Definition: OTPassword.cpp:881
EXPORT OTPassword & operator=(const OTPassword &rhs)
Definition: OTPassword.cpp:466
EXPORT int32_t randomizeMemory(uint32_t size=DEFAULT_SIZE)
Definition: OTPassword.cpp:890
EXPORT bool SetSize(uint32_t size)
Definition: OTPassword.cpp:758
static EXPORT OTPassword * CreateTextBuffer()
Definition: OTPassword.cpp:429
static size_t safe_strlen(const char *s, size_t max)
Definition: OTString.cpp:388
#define OT_LARGE_BLOCKSIZE
Definition: OTCallback.hpp:172
void * ot_secure_memset(void *v, uint8_t c, uint32_t n)
Definition: OTPassword.cpp:177
#define OT_ASSERT(x)
Definition: Assert.hpp:150
#define OT_ASSERT_MSG(x, s)
Definition: Assert.hpp:155
EXPORT uint32_t getPasswordSize() const
Definition: OTPassword.cpp:613
EXPORT const char * getPassword() const
Definition: OTPassword.cpp:547
#define OT_FAIL_MSG(s)
Definition: Assert.hpp:144
bool ot_lockPage(void *addr, size_t len)
Definition: OTPassword.cpp:234
#define munlock(a, b)
Definition: OTPassword.cpp:160
OTLOG_IMPORT OTLogStream otErr
EXPORT const uint8_t * getPassword_uint8() const
Definition: OTPassword.cpp:554
EXPORT bool isMemory() const
Definition: OTPassword.cpp:542
EXPORT void * getMemoryWritable()
Definition: OTPassword.cpp:589
EXPORT int32_t randomizePassword(uint32_t size=DEFAULT_SIZE)
Definition: OTPassword.cpp:823
EXPORT int32_t setPassword_uint8(const uint8_t *input, uint32_t size)
Definition: OTPassword.cpp:674
EXPORT uint32_t getBlockSize() const
Definition: OTPassword.cpp:595
#define OT_DEFAULT_BLOCKSIZE
Definition: OTCallback.hpp:176
EXPORT bool Compare(OTPassword &rhs) const
Definition: OTPassword.cpp:637
static EXPORT void * safe_memcpy(void *dest, uint32_t dsize, const void *src, uint32_t ssize, bool zeroSource=false)
Definition: OTPassword.cpp:357