FW: SFL bug with 512-bit DSA Certificates

"Colestock, Robert" <[email protected]> Tue, 16 Apr 2002 11:44:48 -0400
Newsgroups gmane.ietf.sfl
Message-ID <[email protected]>
FILES DELETED FOR GENERAL DISTRIBUTION!

-----Original Message-----
From: Colestock, Robert 
Sent: Monday, April 15, 2002 11:23 PM
To: '[email protected]'
Cc: '[email protected]'
Subject: RE: SFL bug with 512-bit DSA Certificates


Jim Craigie/John Stark:

Some good news, some bad news.  First please let me apologize for the
inconvenience and thank you for your detailed response.  Much of our
inner crypto logic is hard-coded to specific lengths.  Some of the logic
was provided by outside sources, other logic is updated as necessary for
specific customer requirements (some of it just plain learning on our
part).  Our focus is to provide SMIME processing and basic crypto.  We
will endeavor to correct any specific failures you encounter.

1.2.3.4.) ... DSAParam lengths not handled for 512 bit DSA keys ...
At one time I had successfully tested verification of 512 bit DSA
signatures.  After testing with your private key (thank you for
providing it), I discovered that the signature operations succeeded, but
the verification failed using the sm_free3 CTIL.  The Signing operation
succeeds because the Private Key is properly formatted, there are no
other references to the actual key length when signing.  I am providing
some source file changes to make the verification work correctly in the
sm_free3 CTIL (so I suggest you rename your originals before replacing
with these sources).  These first, then I'll address the remainder of
your issues.  I am providing my current baseline sources, but they may
not work with your version, so I will list the actual changes (minimal):

<<<<<<<< in ./SMIME/libCtilMgr/src/sm_CtilCommon.cpp, around line16 in
the constructor
...
   m_lParamLength = 128;		// DEFAULT
...
<<<<<<<< around line 90, for 64 byte DSA Decode
...
       m_lParamLength = paramLen;
...
<<<<<<<< around line 141, for 128 byte DSA Decode
...
      m_lParamLength = SM_DSA_P_LEN;
...





<<<<<<<< in ./SMIME/libCtilMgr/inc/sm_CtilCommon.h, around line 20 in
the CSM_DSAParams class definition
...
       long m_lParamLength;
...



<<<<<<<< in ./SMIME/alg_libs/sm_free3/sm_free3.cpp, around line 512 in
the SMTI_VerifyDSA(...) method
...
      CSM_DSAParams dsaParameters;

      SME(dsaParameters.Decode(pParams));

      pP = new Integer((const unsigned char *)dsaParameters.P,
dsaParameters.m_lParamLength);
      pQ = new Integer((const unsigned char *)dsaParameters.Q,
SM_DSA_Q_LEN);
      pG = new Integer((const unsigned char *)dsaParameters.G,
dsaParameters.m_lParamLength);
...





Now, onto your other comments.  You are, of course, correct in your
assertions.  The library continues to improve as the need arises.  The
changes above will allow the sm_free3 CTIL to properly sign and verify
512 AND 1024 bit DSA keys.  The internal
CSM_Common::SMTI_VerifyInternalDSA(...) method executes a license
un-encumbered source for DSA signature verification (true free-ware).
At one time I had attempted to make this source handel 512 bit keys, but
was unsuccessful (gave up after 12 hours work).  If you looked at this
code (./SMIME/libCtilMgr/src/fortezza.cpp), then you already know why it
is difficult to modify ("C" written by someone I assume started life as
an assembly programmer!).  At this point we have no plans to update the
internal DSA verify logic to handle 512 bit DSA keys.

My solution was to upgrade the sm_free3 CTIL sources since the Crypto++
classes were much more flexible.  The MS CAPI CTIL also works
appropriately, since the CAPI interface handle all of the crypto
details.


5.) ... CSM_DSAParams ...
This method is only used by our test library for fixed length DSA keys
(we do not have any customers that use 512 bit keys; all of our test
utilities create 1024 bits DSA keys).  One of the SetDSAParams(...)
methods will handle variable length keys.  I have updated the other to
detect 512 or 1024 bit key lengths.  Thank you.

6.) ... CSM_Free3::ExtractParams() ...
Updated to recognize the integer length as 512 or 1024 bit keys.  Thank
you.


<<<Incidentally, the sm_free3.cpp source makes similar assumptions that
<<<Diffie-Hellman keys are 1024-bit.  I have not listed these.
This code will be left intact due to a lack of customer use/interest.
If you encounter any problems, or wish to contibute any updatesd, you
are welcome to do so, we will baseline any changes that keep backward
compatibility.


<<<Finally, here is a code snippet illustrating my statement that the
<<<content-encryption algorithm key sizes for Triple-DES and RC2 are 
I did not realize that 3DES key lengths could be modified.
I believe that the RC2 key generation length is specified in the SMIME
RFCs, so our library only generates a specific key length.  Up until
now, no one has expressed any interest in allowing a variable RC2
encryption length.  As to decryption, it is appropriately decoded from
the RC2 parameter, not hard-coded.  If you require such flexibility in
encrypting, this could be added.


Bob Colestock

-----Original Message-----
From: Jim Craigie
To: Pawling, John
Cc: [email protected]
Sent: 4/11/2002 1:39 PM
Subject: Re: SFL bug with 512-bit DSA Certificates

John Stark writes:

Here are some details of where I have found assumptions within the SFL
2.0.1
code that DSA keys are always 1024-bit.  This list should not be
regarded as
definitive - there could be other code areas which I have not found that
also require attention to fix the problem.

The DSA/DSS spec can be found online at:
http://www.itl.nist.gov/fipspubs/fip186.htm
This indicates that DSA keys may be of any strength (== modulus size) in
the
range 512-1024 that is a multiple of 64.  However it is conventional to
use
powers of two (i.e. 512 or 1024).

SFL 2.0.1 file paths referred to below are relative to unpacked
distribution.  N.B. some of the line numbers could differ slightly in
the
original distribution since this information was taken from our source
that
has been ported to Solaris and had our own fixes applied.

1. SMIME/libCtilMgr/include/sm_apiCtilMgr.h, line 60:

  // Algorithm parameters
  oedefine SM_DSA_P_LEN       128
  oedefine SM_DSA_Q_LEN       20
  oedefine SM_DSA_G_LEN       128

In fact only Q is fixed at 20 bytes.  Both P and G may vary between 64
and
128 bytes.

2. SMIME/libCtilMgr/include/sm_CtilCommon.h, line 12:

  class LIBCTILMGRDLL_API CSM_DSAParams
  {
      public:
         char       *P;
         char       *Q;
         char       *G;
         CSM_DSAParams();
         ~CSM_DSAParams();
         SM_RET_VAL Decode(CSM_Buffer *pParams);
  };

This class has no data field to indicate the size of the P and G values.
Where code elsewhere uses DSA parameters in this class, it has to assume
the
oedefined values referred to above.

3. SMIME/libCtilMgr/src/sm_CtilCommon.cpp, line 57 in
CSM_DSAParams::Decode():

      if (pSnaccV3CertParams->p.Len() <= 65)
           pParamSize = 64;     // Smaller signature.
       else
           pParamSize = SM_DSA_P_LEN; // larger signature.

This code seems to assume that the size may be either 512-bit or
1024-bit.
Also pParamSize is a local variable that needs to be stored in the
CSM_DSAParams class as described above.  I have ignored the "V1
certificate"
code that makes extensive use of the hardwired lengths.

4. SMIME/alg_libs/sm_free3/sm_free3.cpp, line 509 in
CSM_Free3::SMTI_VerifyDSA():

     CSM_DSAParams dsaParameters;
      SME(dsaParameters.Decode(pParams));
      pP = new Integer((const unsigned char *)dsaParameters.P,
SM_DSA_P_LEN);
      pQ = new Integer((const unsigned char *)dsaParameters.Q,
SM_DSA_Q_LEN);
      pG = new Integer((const unsigned char *)dsaParameters.G,
SM_DSA_G_LEN);

This is, I believe, the code that actually causes the problem we observe
with our 512-bit certificates.  Because dsaParameters doesn't contain
the
length, this code has to assume the defaults for 1024-bit.  The Integers
that are constructed end up padded with garbage.

5. SMIME/alg_libs/sm_free3/sm_free3.cpp, line 2715 in
CSM_Free3::SetDSAParams():

  void CSM_Free3::SetDSAParams(AsnInt &P, AsnInt &Q, AsnInt &G)
  {
      CryptoPP::Integer *pTmpBI;
      pTmpBI = ComputeBigInteger(P, 128);
      m_DSAP = *pTmpBI;
      delete pTmpBI;
      pTmpBI = ComputeBigInteger(Q, 20);
      m_DSAQ = *pTmpBI;
      delete pTmpBI;
      pTmpBI = ComputeBigInteger(G, 128);
      m_DSAG = *pTmpBI;
      delete pTmpBI;
  }

This assumes numeric constant parameter sizes, not even the oedefined
values.

6. SMIME/alg_libs/sm_free3/sm_free3.cpp, line 3136 in
CSM_Free3::ExtractParams():

  else if (pAlgID->algorithm == id_dsa ||
            pAlgID->algorithm == id_dsa_with_sha1)
   {
      //byte *pbyte;
      // ASN.1 decode pParams as DSA parameters
      // store them in m_DSAP, m_DSAQ, and m_DSAG
      FREE_DSAParameters snaccDSAParams;
      DECODE_ANY((&snaccDSAParams), (pAlgID->parameters));
      // extract P
      Integer *pTmpBI;
      pTmpBI = ComputeBigInteger(snaccDSAParams.p, 128);
      //pbyte = (byte *)((char*)snaccDSAParams.p);
      m_DSAP = *pTmpBI; //RWC;.Decode(pbyte, snaccDSAParams.p.Len());
      delete pTmpBI;
      // extract Q
      pTmpBI = ComputeBigInteger(snaccDSAParams.q, 20);
      //pbyte = (byte *)((char*)snaccDSAParams.q);
      m_DSAQ = *pTmpBI; //RWC;.Decode(pbyte, snaccDSAParams.q.Len());
      delete pTmpBI;
      // extract G
      pTmpBI = ComputeBigInteger(snaccDSAParams.g, 128);
      //pbyte = (byte *)((char*)snaccDSAParams.g);
      m_DSAG = *pTmpBI; //RWC;.Decode(pbyte, snaccDSAParams.g.Len());
      delete pTmpBI;
   }

This similarly uses numeric constants for the parameter sizes.

Incidentally, the sm_free3.cpp source makes similar assumptions that
Diffie-Hellman keys are 1024-bit.  I have not listed these.

Finally, here is a code snippet illustrating my statement that the
content-encryption algorithm key sizes for Triple-DES and RC2 are fixed:

SMIME/alg_libs/sm_free3/sm_free3.cpp, line 849 in
CSM_Free3::EncryptCryptoPP():

      if (*pPreferredOID == des_ede3_cbc)
      {
         CBC_Length = SM_COMMON_3DES_BLOCKSIZE;
         CBC_KeyLength = SM_COMMON_3DES_KEYLEN;
      }
      else if (*pPreferredOID == rc2_cbc || *pPreferredOID ==
id_alg_CMSRC2wrap)
      {
         CBC_Length = SM_COMMON_RC2_BLOCKSIZE; // 8
         CBC_KeyLength = SM_COMMON_RC2_KEYLEN; // byte count 16
      }
      else if (*pPreferredOID == dES_CBC)
      {
         CBC_Length = SM_COMMON_3DES_BLOCKSIZE;
         CBC_KeyLength = 8;                     // for DES.
      }
      else          // Default to 3DES length.
      {
         CBC_Length = SM_COMMON_3DES_BLOCKSIZE;
         CBC_KeyLength = SM_COMMON_3DES_KEYLEN;
      }


John Stark
E-mail: [email protected]
Tel: +44 (0) 1223 566732
Fax: +44 (0) 1223 566727
Mobile: +44 (0) 7968 110628



-----------------------------------------------------------------------

Clearswift monitors, controls and protects all its messaging traffic in
compliance with its 
corporate email policy using Clearswift products. Find out more about
Clearswift, its 
solutions and services at http://www.clearswift.com

************************************************************************
********************************
This communication is confidential and may contain privileged
information intended solely 
for the named addressee(s). It may not be used or disclosed except for
the purpose for 
which it has been sent. If you are not the intended recipient, you must
not copy, distribute 
or take any action in reliance on it. Unless expressly stated, opinions
in this message are 
those of the individual sender and not of Clearswift. If you have
received this communication
in error, please notify Clearswift by emailing [email protected]
quoting the sender and
delete the message and any attached documents. Clearswift accepts no
liability or 
responsibility for any onward transmission or use of emails and
attachments having left the 
Clearswift domain.