cypher.cxx
上传用户:hzhsqp
上传日期:2007-01-06
资源大小:1600k
文件大小:22k
源码类别:

IP电话/视频会议

开发平台:

Visual C++

  1. /*
  2.  * cypher.cxx
  3.  *
  4.  * Encryption support classes.
  5.  *
  6.  * Portable Windows Library
  7.  *
  8.  * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
  9.  *
  10.  * The contents of this file are subject to the Mozilla Public License
  11.  * Version 1.0 (the "License"); you may not use this file except in
  12.  * compliance with the License. You may obtain a copy of the License at
  13.  * http://www.mozilla.org/MPL/
  14.  *
  15.  * Software distributed under the License is distributed on an "AS IS"
  16.  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  17.  * the License for the specific language governing rights and limitations
  18.  * under the License.
  19.  *
  20.  * The Original Code is Portable Windows Library.
  21.  *
  22.  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
  23.  *
  24.  * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
  25.  * All Rights Reserved.
  26.  *
  27.  * Contributor(s): ______________________________________.
  28.  *
  29.  * $Log: cypher.cxx,v $
  30.  * Revision 1.27  2000/02/17 12:05:02  robertj
  31.  * Added better random number generator after finding major flaws in MSVCRT version.
  32.  *
  33.  * Revision 1.26  1998/11/30 04:50:45  robertj
  34.  * New directory structure
  35.  *
  36.  * Revision 1.25  1998/09/23 06:21:56  robertj
  37.  * Added open source copyright license.
  38.  *
  39.  * Revision 1.24  1998/07/24 06:58:13  robertj
  40.  * Improved robustness of encrypted data decoding, error on illegal tail block size.
  41.  *
  42.  * Revision 1.23  1998/02/16 00:14:36  robertj
  43.  * Fixed ability to register in one stage instead of always having to use 2.
  44.  *
  45.  * Revision 1.22  1998/01/26 02:49:14  robertj
  46.  * GNU support.
  47.  *
  48.  * Revision 1.21  1997/10/30 10:19:19  robertj
  49.  * Fixed bug with having empty string in encrypted text.
  50.  *
  51.  * Revision 1.20  1997/10/10 10:43:41  robertj
  52.  * Fixed bug in password encryption, missing string terminator.
  53.  *
  54.  * Revision 1.19  1997/08/04 10:39:53  robertj
  55.  * Fixed bug for decoding empty string.
  56.  *
  57.  * Revision 1.18  1997/07/26 11:35:38  robertj
  58.  * Fixed bug where illegal data errors were not propagated.
  59.  *
  60.  * Revision 1.17  1996/11/16 10:50:26  robertj
  61.  * ??
  62.  *
  63.  * Revision 1.16  1996/08/17 09:56:02  robertj
  64.  * Fixed big endian processor platform conformance.
  65.  *
  66.  * Revision 1.15  1996/07/15 10:33:42  robertj
  67.  * Changed memory block base64 conversion functions to be void *.
  68.  * Changed memory block cypher conversion functions to be void *.
  69.  * Changed endian classes to be memory mapped.
  70.  *
  71.  * Revision 1.14  1996/06/18 12:35:49  robertj
  72.  * Fixed bug in registration when language is not English.
  73.  *
  74.  * Revision 1.13  1996/06/10 10:01:23  robertj
  75.  * Fixed bug in getting cypher key, not copying all the bytes.
  76.  *
  77.  * Revision 1.12  1996/05/26 03:46:31  robertj
  78.  * Compatibility to GNU 2.7.x
  79.  *
  80.  * Revision 1.11  1996/04/09 03:32:45  robertj
  81.  * Fixed bug in registration so now works in time zones other than Eastern Australia.
  82.  *
  83.  * Revision 1.11  1996/04/08 05:18:38  robertj
  84.  * Fixed bug in registering programs in a different time zone.
  85.  *
  86.  * Revision 1.10  1996/03/17 05:47:19  robertj
  87.  * Changed secured config to allow for expiry dates.
  88.  *
  89.  * Revision 1.9  1996/03/16 04:37:20  robertj
  90.  * Redesign of secure config to accommodate expiry dates and option values passed in security key code.
  91.  *
  92.  * Revision 1.8  1996/03/11 10:28:53  robertj
  93.  * Fixed bug in C++ optimising compiler.
  94.  *
  95.  * Revision 1.7  1996/03/02 03:20:52  robertj
  96.  * Fixed secured config parameters so leading/trailing blanks not significant.
  97.  *
  98.  * Revision 1.6  1996/02/25 11:22:42  robertj
  99.  * Added assertion if try and SetValidation when not pending.
  100.  *
  101.  * Revision 1.5  1996/02/25 02:53:05  robertj
  102.  * Further secure config development.
  103.  *
  104.  * Revision 1.4  1996/02/15 14:43:28  robertj
  105.  * Allowed no secured config data at all to be "valid". All vars will then be guarenteed to default.
  106.  *
  107.  * Revision 1.3  1996/01/28 14:14:12  robertj
  108.  * Further implementation of secure config.
  109.  *
  110.  * Revision 1.2  1996/01/28 02:49:00  robertj
  111.  * Removal of MemoryPointer classes as usage didn't work for GNU.
  112.  * Added the secure configuration mechanism for protecting applications.
  113.  *
  114.  * Revision 1.1  1996/01/23 13:05:58  robertj
  115.  * Initial revision
  116.  *
  117.  */
  118. #ifdef __GNUC__
  119. #pragma implementation "cypher.h"
  120. #endif
  121. #include <ptlib.h>
  122. #include <ptclib/cypher.h>
  123. #include <ptclib/mime.h>
  124. #include <ptclib/random.h>
  125. ///////////////////////////////////////////////////////////////////////////////
  126. // PMessageDigest5
  127. PMessageDigest5::PMessageDigest5()
  128. {
  129.   Start();
  130. }
  131. // Constants for MD5Transform routine.
  132. #define S11 7
  133. #define S12 12
  134. #define S13 17
  135. #define S14 22
  136. #define S21 5
  137. #define S22 9
  138. #define S23 14
  139. #define S24 20
  140. #define S31 4
  141. #define S32 11
  142. #define S33 16
  143. #define S34 23
  144. #define S41 6
  145. #define S42 10
  146. #define S43 15
  147. #define S44 21
  148. // F, G, H and I are basic MD5 functions.
  149. #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
  150. #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
  151. #define H(x, y, z) ((x) ^ (y) ^ (z))
  152. #define I(x, y, z) ((y) ^ ((x) | (~z)))
  153. // ROTATE_LEFT rotates x left n bits.
  154. #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
  155. // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
  156. // Rotation is separate from addition to prevent recomputation.
  157. #define FF(a, b, c, d, x, s, ac) 
  158.  (a) += F ((b), (c), (d)) + (x) + (DWORD)(ac); 
  159.  (a) = ROTATE_LEFT ((a), (s)); 
  160.  (a) += (b); 
  161. #define GG(a, b, c, d, x, s, ac) 
  162.  (a) += G ((b), (c), (d)) + (x) + (DWORD)(ac); 
  163.  (a) = ROTATE_LEFT ((a), (s)); 
  164.  (a) += (b); 
  165. #define HH(a, b, c, d, x, s, ac) 
  166.  (a) += H ((b), (c), (d)) + (x) + (DWORD)(ac); 
  167.  (a) = ROTATE_LEFT ((a), (s)); 
  168.  (a) += (b); 
  169. #define II(a, b, c, d, x, s, ac) 
  170.  (a) += I ((b), (c), (d)) + (x) + (DWORD)(ac); 
  171.  (a) = ROTATE_LEFT ((a), (s)); 
  172.  (a) += (b); 
  173. void PMessageDigest5::Transform(const BYTE * block)
  174. {
  175.   DWORD a = state[0];
  176.   DWORD b = state[1];
  177.   DWORD c = state[2];
  178.   DWORD d = state[3];
  179.   DWORD x[16];
  180.   for (PINDEX i = 0; i < 16; i++)
  181.     x[i] = ((PUInt32l*)block)[i];
  182.   /* Round 1 */
  183.   FF(a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
  184.   FF(d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
  185.   FF(c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
  186.   FF(b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
  187.   FF(a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
  188.   FF(d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
  189.   FF(c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
  190.   FF(b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
  191.   FF(a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
  192.   FF(d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
  193.   FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
  194.   FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
  195.   FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
  196.   FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
  197.   FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
  198.   FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
  199.  /* Round 2 */
  200.   GG(a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
  201.   GG(d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
  202.   GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
  203.   GG(b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
  204.   GG(a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
  205.   GG(d, a, b, c, x[10], S22,  0x2441453); /* 22 */
  206.   GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
  207.   GG(b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
  208.   GG(a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
  209.   GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
  210.   GG(c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
  211.   GG(b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
  212.   GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
  213.   GG(d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
  214.   GG(c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
  215.   GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
  216.   /* Round 3 */
  217.   HH(a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
  218.   HH(d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
  219.   HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
  220.   HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
  221.   HH(a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
  222.   HH(d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
  223.   HH(c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
  224.   HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
  225.   HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
  226.   HH(d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
  227.   HH(c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
  228.   HH(b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
  229.   HH(a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
  230.   HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
  231.   HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
  232.   HH(b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
  233.   /* Round 4 */
  234.   II(a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
  235.   II(d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
  236.   II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
  237.   II(b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
  238.   II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
  239.   II(d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
  240.   II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
  241.   II(b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
  242.   II(a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
  243.   II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
  244.   II(c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
  245.   II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
  246.   II(a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
  247.   II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
  248.   II(c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
  249.   II(b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
  250.   state[0] += a;
  251.   state[1] += b;
  252.   state[2] += c;
  253.   state[3] += d;
  254.   // Zeroize sensitive information.
  255.   memset(x, 0, sizeof(x));
  256. }
  257. void PMessageDigest5::Start()
  258. {
  259.   // Load magic initialization constants.
  260.   state[0] = 0x67452301;
  261.   state[1] = 0xefcdab89;
  262.   state[2] = 0x98badcfe;
  263.   state[3] = 0x10325476;
  264.   count = 0;
  265. }
  266. void PMessageDigest5::Process(const PString & str)
  267. {
  268.   Process((const char *)str);
  269. }
  270. void PMessageDigest5::Process(const char * cstr)
  271. {
  272.   Process(cstr, strlen(cstr));
  273. }
  274. void PMessageDigest5::Process(const PBYTEArray & data)
  275. {
  276.   Process(data, data.GetSize());
  277. }
  278. void PMessageDigest5::Process(const void * dataPtr, PINDEX length)
  279. {
  280.   const BYTE * data = (const BYTE *)dataPtr;
  281.   // Compute number of bytes mod 64
  282.   PINDEX index = (PINDEX)((count >> 3) & 0x3F);
  283.   PINDEX partLen = 64 - index;
  284.   // Update number of bits
  285.   count += (PUInt64)length << 3;
  286.   // See if have a buffer full
  287.   PINDEX i;
  288.   if (length < partLen)
  289.     i = 0;
  290.   else {
  291.     // Transform as many times as possible.
  292.     memcpy(&buffer[index], data, partLen);
  293.     Transform(buffer);
  294.     for (i = partLen; i + 63 < length; i += 64)
  295.       Transform(&data[i]);
  296.     index = 0;
  297.   }
  298.   // Buffer remaining input
  299.   memcpy(&buffer[index], &data[i], length-i);
  300. }
  301. PString PMessageDigest5::Complete()
  302. {
  303.   Code result;
  304.   Complete(result);
  305.   return PBase64::Encode(&result, sizeof(result));
  306. }
  307. void PMessageDigest5::Complete(Code & result)
  308. {
  309.   // Put the count into bytes platform independently
  310.   PUInt64l countBytes = count;
  311.   // Pad out to 56 mod 64.
  312.   PINDEX index = (PINDEX)((count >> 3) & 0x3f);
  313.   PINDEX padLen = (index < 56) ? (56 - index) : (120 - index);
  314.   static BYTE const padding[64] = {
  315.     0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  316.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  317.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  318.   };
  319.   Process(padding, padLen);
  320.   // Append length
  321.   Process(&countBytes, sizeof(countBytes));
  322.   // Store state in digest
  323.   for (PINDEX i = 0; i < PARRAYSIZE(state); i++)
  324.     result.value[i] = state[i];
  325.   // Zeroize sensitive information.
  326.   memset(this, 0, sizeof(*this));
  327. }
  328. PString PMessageDigest5::Encode(const PString & str)
  329. {
  330.   return Encode((const char *)str);
  331. }
  332. void PMessageDigest5::Encode(const PString & str, Code & result)
  333. {
  334.   Encode((const char *)str, result);
  335. }
  336. PString PMessageDigest5::Encode(const char * cstr)
  337. {
  338.   return Encode((const BYTE *)cstr, strlen(cstr));
  339. }
  340. void PMessageDigest5::Encode(const char * cstr, Code & result)
  341. {
  342.   Encode((const BYTE *)cstr, strlen(cstr), result);
  343. }
  344. PString PMessageDigest5::Encode(const PBYTEArray & data)
  345. {
  346.   return Encode(data, data.GetSize());
  347. }
  348. void PMessageDigest5::Encode(const PBYTEArray & data, Code & result)
  349. {
  350.   Encode(data, data.GetSize(), result);
  351. }
  352. PString PMessageDigest5::Encode(const void * data, PINDEX length)
  353. {
  354.   Code result;
  355.   Encode(data, length, result);
  356.   return PBase64::Encode(&result, sizeof(result));
  357. }
  358. void PMessageDigest5::Encode(const void * data, PINDEX len, Code & result)
  359. {
  360.   PMessageDigest5 stomach;
  361.   stomach.Process(data, len);
  362.   stomach.Complete(result);
  363. }
  364. ///////////////////////////////////////////////////////////////////////////////
  365. // PCypher
  366. PCypher::PCypher(PINDEX blkSize, BlockChainMode mode)
  367.   : blockSize(blkSize),
  368.     chainMode(mode)
  369. {
  370. }
  371. PCypher::PCypher(const void * keyData, PINDEX keyLength,
  372.                  PINDEX blkSize, BlockChainMode mode)
  373.   : key((const BYTE *)keyData, keyLength),
  374.     blockSize(blkSize),
  375.     chainMode(mode)
  376. {
  377. }
  378. PString PCypher::Encode(const PString & str)
  379. {
  380.   return Encode((const char *)str, str.GetLength());
  381. }
  382. PString PCypher::Encode(const PBYTEArray & clear)
  383. {
  384.   return Encode((const BYTE *)clear, clear.GetSize());
  385. }
  386. PString PCypher::Encode(const void * data, PINDEX length)
  387. {
  388.   PBYTEArray coded;
  389.   Encode(data, length, coded);
  390.   return PBase64::Encode(coded);
  391. }
  392. void PCypher::Encode(const PBYTEArray & clear, PBYTEArray & coded)
  393. {
  394.   Encode((const BYTE *)clear, clear.GetSize(), coded);
  395. }
  396. void PCypher::Encode(const void * data, PINDEX length, PBYTEArray & coded)
  397. {
  398.   PAssert((blockSize%8) == 0, PUnsupportedFeature);
  399.   Initialise(TRUE);
  400.   const BYTE * in = (const BYTE *)data;
  401.   BYTE * out = coded.GetPointer(
  402.                       blockSize > 1 ? (length/blockSize+1)*blockSize : length);
  403.   while (length >= blockSize) {
  404.     EncodeBlock(in, out);
  405.     in += blockSize;
  406.     out += blockSize;
  407.     length -= blockSize;
  408.   }
  409.   if (blockSize > 1) {
  410.     PBYTEArray extra(blockSize);
  411.     extra[blockSize-1] = (BYTE)length;
  412.     for (PINDEX i = 0; i < length; i++)
  413.       extra[i] = *in++;
  414.     EncodeBlock(extra, out);
  415.   }
  416. }
  417. PString PCypher::Decode(const PString & cypher)
  418. {
  419.   PString clear;
  420.   if (Decode(cypher, clear))
  421.     return clear;
  422.   return PString();
  423. }
  424. BOOL PCypher::Decode(const PString & cypher, PString & clear)
  425. {
  426.   clear = PString();
  427.   PBYTEArray clearText;
  428.   if (!Decode(cypher, clearText))
  429.     return FALSE;
  430.   if (clearText.IsEmpty())
  431.     return TRUE;
  432.   PINDEX sz = clearText.GetSize();
  433.   memcpy(clear.GetPointer(sz+1), (const BYTE *)clearText, sz);
  434.   return TRUE;
  435. }
  436. BOOL PCypher::Decode(const PString & cypher, PBYTEArray & clear)
  437. {
  438.   PBYTEArray coded;
  439.   if (!PBase64::Decode(cypher, coded))
  440.     return FALSE;
  441.   return Decode(coded, clear);
  442. }
  443. PINDEX PCypher::Decode(const PString & cypher, void * data, PINDEX length)
  444. {
  445.   PBYTEArray coded;
  446.   PBase64::Decode(cypher, coded);
  447.   PBYTEArray clear;
  448.   if (!Decode(coded, clear))
  449.     return 0;
  450.   memcpy(data, clear, PMIN(length, clear.GetSize()));
  451.   return clear.GetSize();
  452. }
  453. PINDEX PCypher::Decode(const PBYTEArray & coded, void * data, PINDEX length)
  454. {
  455.   PBYTEArray clear;
  456.   if (!Decode(coded, clear))
  457.     return 0;
  458.   memcpy(data, coded, PMIN(length, clear.GetSize()));
  459.   return clear.GetSize();
  460. }
  461. BOOL PCypher::Decode(const PBYTEArray & coded, PBYTEArray & clear)
  462. {
  463.   PAssert((blockSize%8) == 0, PUnsupportedFeature);
  464.   if (coded.IsEmpty() || (coded.GetSize()%blockSize) != 0)
  465.     return FALSE;
  466.   Initialise(FALSE);
  467.   const BYTE * in = coded;
  468.   PINDEX length = coded.GetSize();
  469.   BYTE * out = clear.GetPointer(length);
  470.   for (PINDEX count = 0; count < length; count += blockSize) {
  471.     DecodeBlock(in, out);
  472.     in += blockSize;
  473.     out += blockSize;
  474.   }
  475.   if (blockSize != 1) {
  476.     if (*--out >= blockSize)
  477.       return FALSE;
  478.     clear.SetSize(length - blockSize + *out);
  479.   }
  480.   return TRUE;
  481. }
  482. ///////////////////////////////////////////////////////////////////////////////
  483. // PTEACypher
  484. PTEACypher::PTEACypher(BlockChainMode chainMode)
  485.   : PCypher(8, chainMode)
  486. {
  487.   GenerateKey(*(Key*)key.GetPointer(sizeof(Key)));
  488. }
  489. PTEACypher::PTEACypher(const Key & keyData, BlockChainMode chainMode)
  490.   : PCypher(&keyData, sizeof(Key), 8, chainMode)
  491. {
  492. }
  493. void PTEACypher::SetKey(const Key & newKey)
  494. {
  495.   memcpy(key.GetPointer(sizeof(Key)), &newKey, sizeof(Key));
  496. }
  497. void PTEACypher::GetKey(Key & newKey) const
  498. {
  499.   memcpy(&newKey, key, sizeof(Key));
  500. }
  501. void PTEACypher::GenerateKey(Key & newKey)
  502. {
  503.   static PRandom rand; //=1 // Explicitly set seed if need known random sequence
  504.   for (PINDEX i = 0; i < sizeof(Key); i++)
  505.     newKey.value[i] = (BYTE)rand;
  506. }
  507. static const DWORD TEADelta = 0x9e3779b9;    // Magic number for key schedule
  508. void PTEACypher::Initialise(BOOL)
  509. {
  510.   k0 = ((const PUInt32l *)(const BYTE *)key)[0];
  511.   k1 = ((const PUInt32l *)(const BYTE *)key)[1];
  512.   k2 = ((const PUInt32l *)(const BYTE *)key)[2];
  513.   k3 = ((const PUInt32l *)(const BYTE *)key)[3];
  514. }
  515. void PTEACypher::EncodeBlock(const void * in, void * out)
  516. {
  517.   DWORD y = ((PUInt32b*)in)[0];
  518.   DWORD z = ((PUInt32b*)in)[1];
  519.   DWORD sum = 0;
  520.   for (PINDEX count = 32; count > 0; count--) {
  521.     sum += TEADelta;    // Magic number for key schedule
  522.     y += (z<<4)+k0 ^ z+sum ^ (z>>5)+k1;
  523.     z += (y<<4)+k2 ^ y+sum ^ (y>>5)+k3;   /* end cycle */
  524.   }
  525.   ((PUInt32b*)out)[0] = y;
  526.   ((PUInt32b*)out)[1] = z;
  527. }
  528. void PTEACypher::DecodeBlock(const void * in, void * out)
  529. {
  530.   DWORD y = ((PUInt32b*)in)[0];
  531.   DWORD z = ((PUInt32b*)in)[1];
  532.   DWORD sum = TEADelta<<5;
  533.   for (PINDEX count = 32; count > 0; count--) {
  534.     z -= (y<<4)+k2 ^ y+sum ^ (y>>5)+k3; 
  535.     y -= (z<<4)+k0 ^ z+sum ^ (z>>5)+k1;
  536.     sum -= TEADelta;    // Magic number for key schedule
  537.   }
  538.   ((PUInt32b*)out)[0] = y;
  539.   ((PUInt32b*)out)[1] = z;
  540. }
  541. ///////////////////////////////////////////////////////////////////////////////
  542. // PSecureConfig
  543. static const char DefaultSecuredOptions[] = "Secured Options";
  544. static const char DefaultSecurityKey[] = "Validation";
  545. static const char DefaultExpiryDateKey[] = "Expiry Date";
  546. static const char DefaultOptionBitsKey[] = "Option Bits";
  547. static const char DefaultPendingPrefix[] = "Pending:";
  548. PSecureConfig::PSecureConfig(const PTEACypher::Key & prodKey,
  549.                              const PStringArray & secKeys,
  550.                              Source src)
  551.   : PConfig(DefaultSecuredOptions, src),
  552.     securedKeys(secKeys),
  553.     securityKey(DefaultSecurityKey),
  554.     expiryDateKey(DefaultExpiryDateKey),
  555.     optionBitsKey(DefaultOptionBitsKey),
  556.     pendingPrefix(DefaultPendingPrefix)
  557. {
  558.   productKey = prodKey;
  559. }
  560. PSecureConfig::PSecureConfig(const PTEACypher::Key & prodKey,
  561.                              const char * const * secKeys,
  562.                              PINDEX count,
  563.                              Source src)
  564.   : PConfig(DefaultSecuredOptions, src),
  565.     securedKeys(count, secKeys),
  566.     securityKey(DefaultSecurityKey),
  567.     expiryDateKey(DefaultExpiryDateKey),
  568.     optionBitsKey(DefaultOptionBitsKey),
  569.     pendingPrefix(DefaultPendingPrefix)
  570. {
  571.   productKey = prodKey;
  572. }
  573. void PSecureConfig::GetProductKey(PTEACypher::Key & prodKey) const
  574. {
  575.   prodKey = productKey;
  576. }
  577. PSecureConfig::ValidationState PSecureConfig::GetValidation() const
  578. {
  579.   PString str;
  580.   BOOL allEmpty = TRUE;
  581.   PMessageDigest5 digestor;
  582.   for (PINDEX i = 0; i < securedKeys.GetSize(); i++) {
  583.     str = GetString(securedKeys[i]);
  584.     if (!str.IsEmpty()) {
  585.       digestor.Process(str.Trim());
  586.       allEmpty = FALSE;
  587.     }
  588.   }
  589.   str = GetString(expiryDateKey);
  590.   if (!str.IsEmpty()) {
  591.     digestor.Process(str);
  592.     allEmpty = FALSE;
  593.   }
  594.   str = GetString(optionBitsKey);
  595.   if (!str.IsEmpty()) {
  596.     digestor.Process(str);
  597.     allEmpty = FALSE;
  598.   }
  599.   PString vkey = GetString(securityKey);
  600.   if (allEmpty)
  601.     return (!vkey || GetBoolean(pendingPrefix + securityKey)) ? Pending : Defaults;
  602.   PMessageDigest5::Code code;
  603.   digestor.Complete(code);
  604.   if (vkey.IsEmpty())
  605.     return Invalid;
  606.   BYTE info[sizeof(code)+1+sizeof(DWORD)];
  607.   PTEACypher crypt(productKey);
  608.   if (crypt.Decode(vkey, info, sizeof(info)) != sizeof(info))
  609.     return Invalid;
  610.   if (memcmp(info, &code, sizeof(code)) != 0)
  611.     return Invalid;
  612.   PTime now;
  613.   if (now > GetTime(expiryDateKey))
  614.     return Expired;
  615.   return IsValid;
  616. }
  617. BOOL PSecureConfig::ValidatePending()
  618. {
  619.   if (GetValidation() != Pending)
  620.     return FALSE;
  621.   PString vkey = GetString(securityKey);
  622.   if (vkey.IsEmpty())
  623.     return TRUE;
  624.   PMessageDigest5::Code code;
  625.   BYTE info[sizeof(code)+1+sizeof(DWORD)];
  626.   PTEACypher crypt(productKey);
  627.   if (crypt.Decode(vkey, info, sizeof(info)) != sizeof(info))
  628.     return FALSE;
  629.   PTime expiryDate(0, 0, 0,
  630.             1, info[sizeof(code)]&15, (info[sizeof(code)]>>4)+1996, PTime::GMT);
  631.   PString expiry = expiryDate.AsString("d MMME yyyy", PTime::GMT);
  632.   // This is for alignment problems on processors that care about such things
  633.   PUInt32b opt;
  634.   void * dst = &opt;
  635.   void * src = &info[sizeof(code)+1];
  636.   memcpy(dst, src, sizeof(opt));
  637.   PString options(PString::Unsigned, (DWORD)opt);
  638.   PMessageDigest5 digestor;
  639.   PINDEX i;
  640.   for (i = 0; i < securedKeys.GetSize(); i++)
  641.     digestor.Process(GetString(pendingPrefix + securedKeys[i]).Trim());
  642.   digestor.Process(expiry);
  643.   digestor.Process(options);
  644.   digestor.Complete(code);
  645.   if (memcmp(info, &code, sizeof(code)) != 0)
  646.     return FALSE;
  647.   SetString(expiryDateKey, expiry);
  648.   SetString(optionBitsKey, options);
  649.   for (i = 0; i < securedKeys.GetSize(); i++) {
  650.     PString str = GetString(pendingPrefix + securedKeys[i]);
  651.     if (!str.IsEmpty())
  652.       SetString(securedKeys[i], str);
  653.     DeleteKey(pendingPrefix + securedKeys[i]);
  654.   }
  655.   DeleteKey(pendingPrefix + securityKey);
  656.   return TRUE;
  657. }
  658. void PSecureConfig::ResetPending()
  659. {
  660.   if (GetBoolean(pendingPrefix + securityKey)) {
  661.     for (PINDEX i = 0; i < securedKeys.GetSize(); i++)
  662.       DeleteKey(securedKeys[i]);
  663.   }
  664.   else {
  665.     SetBoolean(pendingPrefix + securityKey, TRUE);
  666.     for (PINDEX i = 0; i < securedKeys.GetSize(); i++) {
  667.       PString str = GetString(securedKeys[i]);
  668.       if (!str.IsEmpty())
  669.         SetString(pendingPrefix + securedKeys[i], str);
  670.       DeleteKey(securedKeys[i]);
  671.     }
  672.   }
  673.   DeleteKey(expiryDateKey);
  674.   DeleteKey(optionBitsKey);
  675. }
  676. ///////////////////////////////////////////////////////////////////////////////