// EGPublicKey::CopyFromPrivateKey
// Copies public key from a private key.  Existing key (if any) is replaced.  This
// method takes the binary rep of the private key and drops the private portion
// to generate the public key.
void
EGPublicKey::CopyFromPrivateKey(const EGPrivateKey& theKeyR)
{
	ClearLocal();

	try
	{
		ByteQueue aPrivQueue;
		aPrivQueue.Put(theKeyR.GetKey(), theKeyR.GetKeyLen());
		aPrivQueue.Close();

		ElGamalVerifier aKey(aPrivQueue);
		ByteQueue       aPubQueue;
		aKey.DEREncode(aPubQueue);
		aPubQueue.Close();

		AllocKeyBuf(aPubQueue.MaxRetrieveable());
		aPubQueue.Get(mKey, mKeyLen);
	}
	catch (Exception& anEx)
	{
		WDBG_AH("EGPublicKey::CopyFromPrivateKey Caught CryptoLib exception: " << anEx.what());
#ifndef _WONCRYPT_NOEXCEPTIONS
		throw WONCrypt::CryptException(WONCommon::ExCryptoLib, __LINE__, __FILE__, anEx.what());
#else
		Invalidate();
#endif
	}
}
Example #2
0
 QByteArray CppGetByteArray(const CryptoMaterial &cm)
 {
   ByteQueue queue;
   cm.Save(queue);
   QByteArray data(queue.CurrentSize(), 0);
   queue.Get(reinterpret_cast<byte *>(data.data()), data.size());
   return data;
 }
Example #3
0
void CAuthenticationProfileImpl::sendPublicKey(RSA::PublicKey publicKey)
{
   LOG4CPLUS_TRACE_METHOD(msLogger, __PRETTY_FUNCTION__ );
   ByteQueue queue;
   publicKey.Save(queue);
   UInt32 queueSize = queue.CurrentSize();
   UInt8* outgoingData = new UInt8[queueSize + 1];
   outgoingData[0] = static_cast<UInt8>(SEND_PUBLIC_KEY);
   queue.Get(outgoingData + 1, queueSize);
   LOG4CPLUS_INFO(msLogger, "***** " + convertIntegerToString(queueSize + 1) + " bytes sent");
   iviLink::Channel::sendBuffer(mChannelID, outgoingData, queueSize + 1);
   delete[] outgoingData;
}
// EGPublicKey::Encrypt
// Encrypts a block of data of the specified length using ElGamal encryption for this
// key.  Returns allocated block/len of encrypted data.
EGPublicKey::CryptReturn
EGPublicKey::Encrypt(const void* theMsgP, unsigned long theLen) const
{
	WTRACE("EGPublicKey::Encrypt");

	// Sanity check
	if ((! theMsgP) || (theLen == 0))
	{
		WDBG_LM("EGPublicKey::Encrypt No data to encrypt");
		return CryptReturn(NULL,0);
	}

	try
	{
		// Allocate crypt object if needed
		AllocateCrypt();

		// Encrypt the data
		ByteQueue aQueue;
		EncryptData(aQueue, reinterpret_cast<const unsigned char*>(theMsgP), theLen);

		// Build return
		WDBG_LL("EGPublicKey::Encrypt Building return values.");
		unsigned long anOutLen = aQueue.MaxRetrieveable();
		if (anOutLen == 0)
		{
			WDBG_LM("EGPublicKey::Encrypt Encrypt failed, no data.");
			return CryptReturn(NULL, 0);
		}

		auto_ptr<unsigned char> anOutP(new unsigned char [anOutLen]);
		aQueue.Get(anOutP.get(), anOutLen);

		WDBG_LM("EGPublicKey::Encrypt Encrypted, out block len=" << anOutLen);
		return CryptReturn(anOutP.release(), anOutLen);
	}
	catch (Exception& anEx)
	{
		// Little trick here, construct a CryptException to auto log the failure!
		WDBG_AH("EGPublicKey::Encrypt Caught CryptoLib exception: " << anEx.what());
#ifndef _WONCRYPT_NOEXCEPTIONS
		WONCrypt::CryptException aLog(WONCommon::ExCryptoLib, __LINE__, __FILE__, anEx.what());
#endif
		return CryptReturn(NULL,0);
	}
}
Example #5
0
void PEM_NextObject(BufferedTransformation& src, BufferedTransformation& dest, bool trimTrailing)
{
    if(!src.AnyRetrievable())
        return;
    
    // We have four things to find:
    //   1. -----BEGIN (the leading begin)
    //   2. ----- (the trailing dashes)
    //   3. -----END (the leading end)
    //   4. ----- (the trailing dashes)
    
    // Once we parse something that purports to be PEM encoded, another routine
    //  will have to look for something particular, like a RSA key. We *will*
    //  inadvertently parse garbage, like -----BEGIN FOO BAR-----. It will
    //  be caught later when a PEM_Load routine is called.
    
    static const size_t BAD_IDX = PEM_INVALID;
    
    // We use iterators for the search. However, an interator is invalidated
    //  after each insert that grows the container. So we save indexes
    //  from begin() to speed up searching. On each iteration, we simply
    //  reinitialize them.
    SecByteBlock::const_iterator it;
    size_t idx1 = BAD_IDX, idx2 = BAD_IDX, idx3 = BAD_IDX, idx4 = BAD_IDX;
    
    // The idea is to read chunks in case there are multiple keys or
    //  paramters in a BufferedTransformation. So we use CopyTo to
    //  extract what we are interested in. We don't take anything
    //  out of the BufferedTransformation (yet).
    
    // We also use indexes because the iterator will be invalidated
    //   when we append to the ByteQueue. Even though the iterator
    //   is invalid, `accum.begin() + index` will be valid.
    
    // Reading 8 or 10 lines at a time is an optimization from testing
    //   against cacerts.pem. The file has 153 certs, so its a good test.
    // +2 to allow for CR + LF line endings. There's no guarantee a line
    //   will be present, or it will be RFC1421_LINE_BREAK in size.
    static const size_t READ_SIZE = (RFC1421_LINE_BREAK + 1) * 10;
    static const size_t REWIND = max(SBB_PEM_BEGIN.size(), SBB_PEM_END.size()) + 2;
    
    SecByteBlock accum;
    size_t idx = 0, next = 0;
    
    size_t available = src.MaxRetrievable();
    while(available)
    {
        // How much can we read?
        const size_t size = std::min(available, READ_SIZE);
        
        // Ideally, we would only scan the line we are reading. However,
        //   we need to rewind a bit in case a token spans the previous
        //   block and the block we are reading. But we can't rewind
        //   into a previous index. Once we find an index, the variable
        //   next is set to it. Hence the reason for the max()
        if(idx > REWIND)
        {
            const size_t x = idx - REWIND;
            next = max(next, x);
        }
        
#if 0
        // Next should be less than index by 10 or so
        std::cout << "  Index: " << idx << std::endl;
        std::cout << "   Next: " << next << std::endl;
#endif
        
        // We need a temp queue to use CopyRangeTo. We have to use it
        //   because there's no Peek that allows us to peek a range.
        ByteQueue tq;
        src.CopyRangeTo(tq, static_cast<lword>(idx), static_cast<lword>(size));
        
        const size_t offset = accum.size();
        accum.Grow(offset + size);
        tq.Get(accum.data() + offset, size);
        
        // Adjust sizes
        idx += size;
        available -= size;
        
        // Locate '-----BEGIN'
        if(idx1 == BAD_IDX)
        {
            it = search(accum.begin() + next, accum.end(), SBB_PEM_BEGIN.begin(), SBB_PEM_BEGIN.end());
            if(it == accum.end())
                continue;
            
            idx1 = it - accum.begin();
            next = idx1 + SBB_PEM_BEGIN.size();
        }
        
        // Locate '-----'
        if(idx2 == BAD_IDX && idx1 != BAD_IDX)
        {
            it = search(accum.begin() + next, accum.end(), SBB_PEM_TAIL.begin(), SBB_PEM_TAIL.end());
            if(it == accum.end())
                continue;
            
            idx2 = it - accum.begin();
            next = idx2 + SBB_PEM_TAIL.size();
        }
        
        // Locate '-----END'
        if(idx3 == BAD_IDX && idx2 != BAD_IDX)
        {
            it = search(accum.begin() + next, accum.end(), SBB_PEM_END.begin(), SBB_PEM_END.end());
            if(it == accum.end())
                continue;
            
            idx3 = it - accum.begin();
            next = idx3 + SBB_PEM_END.size();
        }
        
        // Locate '-----'
        if(idx4 == BAD_IDX && idx3 != BAD_IDX)
        {
            it = search(accum.begin() + next, accum.end(), SBB_PEM_TAIL.begin(), SBB_PEM_TAIL.end());
            if(it == accum.end())
                continue;
            
            idx4 = it - accum.begin();
            next = idx4 + SBB_PEM_TAIL.size();
        }
    }
    
    // Did we find `-----BEGIN XXX-----` (RFC 1421 calls this pre-encapsulated boundary)?
    if(idx1 == BAD_IDX || idx2 == BAD_IDX)
        throw InvalidDataFormat("PEM_NextObject: could not locate boundary header");
    
    // Did we find `-----END XXX-----` (RFC 1421 calls this post-encapsulated boundary)?
    if(idx3 == BAD_IDX || idx4 == BAD_IDX)
        throw InvalidDataFormat("PEM_NextObject: could not locate boundary footer");
    
    // *IF* the trailing '-----' occurred in the last 5 bytes in accum, then we might miss the
    // End of Line. We need to peek 2 more bytes if available and append them to accum.
    if(available >= 2)
    {
        ByteQueue tq;
        src.CopyRangeTo(tq, static_cast<lword>(idx), static_cast<lword>(2));
        
        const size_t offset = accum.size();
        accum.Grow(offset + 2);
        tq.Get(accum.data() + offset, 2);
    }
    else if(available == 1)
    {
        ByteQueue tq;
        src.CopyRangeTo(tq, static_cast<lword>(idx), static_cast<lword>(1));
        
        const size_t offset = accum.size();
        accum.Grow(offset + 1);
        tq.Get(accum.data() + offset, 1);
    }
    
    // Final book keeping
    const byte* ptr = accum.begin() + idx1;
    const size_t used = idx4 + SBB_PEM_TAIL.size();
    const size_t len = used - idx1;
    
    // Include one CR/LF if its available in the accumulator
    next = idx1 + len;
    size_t adjust = 0;
    if(next < accum.size())
    {
        byte c1 = accum[next];
        byte c2 = 0;
        
        if(next + 1 < accum.size())
            c2 = accum[next + 1];
        
        // Longest match first
        if(c1 == '\r' && c2 == '\n')
            adjust = 2;
        else if(c1 == '\r' || c1 == '\n')
            adjust = 1;
    }
    
    dest.Put(ptr, len + adjust);
    dest.MessageEnd();
    
    src.Skip(used + adjust);
    
    if(trimTrailing)
    {
        while (src.AnyRetrievable())
        {
            byte b;
            src.Peek(b);
            
            if(!isspace(b)) break;
            src.Skip(1);
        }
    }
}
Example #6
0
size_t PEM_ReadLine(BufferedTransformation& source, SecByteBlock& line, SecByteBlock& ending)
{
    if(!source.AnyRetrievable())
    {
        line.New(0);
        ending.New(0);
        
        return 0;
    }
    
    ByteQueue temp;
    
    while(source.AnyRetrievable())
    {
        byte b;
        if(!source.Get(b))
            throw Exception(Exception::OTHER_ERROR, "PEM_ReadLine: failed to read byte");
        
        // LF ?
        if(b == '\n')
        {
            ending = LF;
            break;
        }
        
        // CR ?
        if(b == '\r')
        {
            // CRLF ?
            if(source.AnyRetrievable() && source.Peek(b))
            {
                if(b == '\n')
                {
                    source.Skip(1);
                    
                    ending = CRLF;
                    break;
                }
            }
            
            ending = CR;
            break;
        }
        
        // Not End-of-Line, accumulate it.
        temp.Put(b);
    }
    
    if(temp.AnyRetrievable())
    {
        line.Grow(temp.MaxRetrievable());
        temp.Get(line.data(), line.size());
    }
    else
    {
        line.New(0);
        ending.New(0);
    }
    
    // We return a line stripped of CRs and LFs. However, we return the actual number of
    //   of bytes processed, including the CR and LF. A return of 0 means nothing was read.
    //   A return of 1 means an empty line was read (CR or LF). A return of 2 could
    //   mean an empty line was read (CRLF), or could mean 1 character was read. In
    //   any case, line will hold whatever was parsed.
    return line.size() + ending.size();
}