Back to index

lightning-sunbird  0.9+nobinonly
nsEntropyCollector.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 2001
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   L. David Baron <dbaron@dbaron.org> (original author)
00024  *   Kai Engert <kaie@netscape.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "prlog.h"
00041 #include "nsEntropyCollector.h"
00042 #include "nsMemory.h"
00043 
00044 nsEntropyCollector::nsEntropyCollector()
00045 :mBytesCollected(0), mWritePointer(mEntropyCache)
00046 {
00047 }
00048 
00049 nsEntropyCollector::~nsEntropyCollector()
00050 {
00051 }
00052 
00053 NS_IMPL_THREADSAFE_ISUPPORTS2(nsEntropyCollector,
00054                               nsIEntropyCollector,
00055                               nsIBufEntropyCollector)
00056 
00057 NS_IMETHODIMP
00058 nsEntropyCollector::RandomUpdate(void *new_entropy, PRInt32 bufLen)
00059 {
00060   if (bufLen > 0) {
00061     if (mForwardTarget) {
00062       return mForwardTarget->RandomUpdate(new_entropy, bufLen);
00063     }
00064     else {
00065       const unsigned char *InputPointer = (const unsigned char *)new_entropy;
00066       const unsigned char *PastEndPointer = mEntropyCache + entropy_buffer_size;
00067 
00068       // if the input is large, we only take as much as we can store
00069       PRInt32 bytes_wanted = PR_MIN(bufLen, entropy_buffer_size);
00070 
00071       // remember the number of bytes we will have after storing new_entropy
00072       mBytesCollected = PR_MIN(entropy_buffer_size, mBytesCollected + bytes_wanted);
00073 
00074       // as the above statements limit bytes_wanted to the entropy_buffer_size,
00075       // this loop will iterate at most twice.
00076       while (bytes_wanted > 0) {
00077 
00078         // how many bytes to end of cyclic buffer?
00079         const PRInt32 space_to_end = PastEndPointer - mWritePointer;
00080 
00081         // how many bytes can we copy, not reaching the end of the buffer?
00082         const PRInt32 this_time = PR_MIN(space_to_end, bytes_wanted);
00083 
00084         // copy at most to the end of the cyclic buffer
00085         for (PRInt32 i = 0; i < this_time; ++i) {
00086 
00087           // accept the fact that we use our buffer's random uninitialized content
00088           unsigned int old = *mWritePointer;
00089 
00090           // combine new and old value already stored in buffer
00091           // this logic comes from PSM 1
00092           *mWritePointer++ = ((old << 1) | (old >> 7)) ^ *InputPointer++;
00093         }
00094 
00095         PR_ASSERT(mWritePointer <= PastEndPointer);
00096         PR_ASSERT(mWritePointer >= mEntropyCache);
00097 
00098         // have we arrived at the end of the buffer?
00099         if (PastEndPointer == mWritePointer) {
00100           // reset write pointer back to begining of our buffer
00101           mWritePointer = mEntropyCache;
00102         }
00103 
00104         // subtract the number of bytes we have already copied
00105         bytes_wanted -= this_time;
00106       }
00107     }
00108   }
00109 
00110   return NS_OK;
00111 }
00112 
00113 NS_IMETHODIMP
00114 nsEntropyCollector::ForwardTo(nsIEntropyCollector *aCollector)
00115 {
00116   NS_PRECONDITION(!mForwardTarget, "|ForwardTo| should only be called once.");
00117 
00118   mForwardTarget = aCollector;
00119   mForwardTarget->RandomUpdate(mEntropyCache, mBytesCollected);
00120   mBytesCollected = 0;
00121 
00122   return NS_OK;
00123 }
00124 
00125 NS_IMETHODIMP
00126 nsEntropyCollector::DontForward()
00127 {
00128   mForwardTarget = nsnull;
00129   return NS_OK;
00130 }