I don't know if this can interest someone on this list, but in the attached
announce, together  with and open source implementation of MS CSP, you can
find a tool that can be used to substitute the _NSAKEY in the advapi32.dll.

ciao
Sergio Tabanelli
Project Manager & Consultant
Fabbrica Servizi Telematici (FST)
[EMAIL PROTECTED]





Hi all.
Two months ago I finished the development of an open source
implementation of a Microsoft RSA FULL Cryptographic Service Provider. My
intention was to make it available through a site in a well packaged
distribution together with some documentation and comments. Now I realized
that I have no time for this so I have decided to distribute it as it is.
Following
is a brief description of my work.
CSPs are the base components of CAPI, witch are widely used by applications
like IE, Outlook, IIS and by lots of other applications with cryptographic
functionalities.
CSP can be loaded only if it is digitally signed by Microsoft.
Unfortunately at
the moment "myCSP" has not been signed by Microsoft.
Actually the only way to use it is to patch the CSP image signature
verification code in the advapi32.dll.
Microsoft has never documented the format and procedure they use to store
private key containers, "myCSP" can read and store RSA keys using
Microsoft's formats, including w2k. 
Here is a brief description of MS formats.

=========Keys storage=======
Depending on the operating system MS CSPs store RSA key containers in three
formats. Before starting it is better to introduce two pseudo structures
widely used by Microsoft for public and private RSA keys.

Struct RSAPubKeyBlob {   // Contains an RSA public key
            DWORD magic;  // Must be 0x31415352
            DWORD nlen; // must be equal to modulus bytes len + 8 (????
Bsafe ????)
            DWORD nbit; // must be equal to modulus bits len
            DWORD nlen1; // must be equal to modulus bytes len -1 (????
Bsafe ????)
            DWORD e; // public exponent
            Unsigned char n[nlen]; // must contains the modulus stored in
little endian and with last 8 bytes set to 0
}

Struct RSAPrivKeyBlob {   // Contains an RSA private key
            DWORD magic;  // Must be 0x32415352
            DWORD nlen; // must be equal to modulus bytes len + 8 (????
Bsafe ????)
            DWORD nbit; // must be equal to modulus bits len
            DWORD nlen1; // must be equal to modulus bytes len -1 (????
Bsafe ????)
            DWORD e; // public exponent
            Unsigned char n[nlen]; // must contains modulus stored in
little
endian with last 8 bytes set to 0
            Unsigned char p[nlen/2]; // must contains prime p stored in
little endian with last 4 bytes set to 0
            Unsigned char q[nlen/2]; // must contains prime q stored in
little endian with last 4 bytes set to 0
            Unsigned char dmp1[nlen/2]; // must contains d mod (p-1) stored
in little endian with last 4 bytes set to 0
            Unsigned char dmq1[nlen/2]; // must contains d mod (q-1) stored
in little endian with last 4 bytes set to 0
            Unsigned char iqmp[nlen/2]; // must contains (inverse of q) mod
p stored in little endian with last 4 bytes set to 0
            Unsigned char d[nlen]; // must contains the private exponent d
stored in little endian with last 8 bytes set to 0
}

======Registry=====
This method is used in W95, NT4 SP <= 4, all container information are
stored in a registry key named as the container, the container registry key
contain the following values:

EExport/Sexport:       Set to 1 if the key is exportable to 0 if not
Epbk/Spbk:                 Contains the serialized RSAPubKeyBlob of the
public key
Epvk/Spvk:                 Contains the serialized RSAPrivKeyBlob of the
private key encrypted with an rc4 key 128 bits long with first 5 bytes
equal
to the first 5 bytes of the MD5 of the container name, and last 11 bytes of
the rc4 key set to 0 (salt).
RandSeed:                  Is a 20 bytes random state buffer used to
initialise and save the random bytes generator state.

==========Registry and Protected
Storage========
This method is used in W98, NT4 SP > 4, public information are stored in
registry, private keys and export flags are stored through the Protected
Storage service:

Epbk/Spbk:                 Contains the serialized RSAPubKeyBlob of the
public key;
PSKEYS:                    Set to 1 if the OS is NT, 2 if not.
SigTypeSubtype/ ExchTypeSubtype: Contains the GUIDs used with Protected
Storage service.

The value stored in the protected storage is the serialization of the
following pseudo structure:

 Struct RSAPSBlob {   // Contains the value stored in the protected storage
            DWORD ExportFlag;  // Set to 1 if the key is exportable to 0 if
not
Struct RSAPrivKeyBlob PrivateKey; // blob containing the RSA private key
}

I have also reverse engineered large part of the protection mechanism used
by the protected storage, but actually I have no time to put it all
and write it down.

======File=========
This method is used in W2K, all container information are stored in a file
with name equal to

MD5Str(container name) + '_' + Machine GUID

Where + means concatenation
MD5Str is the MD5 hexadecimal string representation of the container name.
Machine GUID is the value of MachineGuid found in the registry key
"Software\Microsoft\Cryptography"

The file contains the serialization of the following pseudo structure

Struct w2kContainer {
            DWORD ver; // must be 2
            DWORD GenKeyType; //  is the ored value of 1 if signature key
pair is present, 2 if exchange key pair is present
            DWORD CNameLen; // CName length
            DWORD SPbkLen; // SPbk length
            DWORD SPvkEncLen; // SPvkEnc length
            DWORD EPbkLen; // EPbk length
            DWORD EPvkEncLen; // EPvkEnc length
            DWORD RandSeedLen; // RandSeed length (20 bytes)
            DWORD SEflagEncLen; // SEflagEnc length
            DWORD EEflagsEncLen; // EEflagEnc length
            unsigned char CName[CNameLen]; // contains the container name
null terminated
            unsigned char SPbk[SpbkLen]; // contains the RSAPubKeyBlob of
the signature public key.
            unsigned char SPvkEnc[SpvkEncLen]; // contains the
RSAPrivKeyBlob of the signature private key protected through the data
protection api.
            unsigned char EPbk[EpbkLen]; // contains the RSAPubKeyBlob of
the exchange public key.
            unsigned char EPvkEnc[EpvkEncLen]; // contains the
RSAPrivKeyBlob of the exchange private key protected through the data
protection api.
            unsigned char RandSeed[RandSeedLen]; // contains the random
state buffer used to initialise and save the random bytes generator state.
            unsigned char SEflagEnc[SEflagEncLen]; // contains the export
flag value of the signature private key protected through the data
protection api.
            unsigned char EEflagEnc[EEflagEncLen]; // contains the export
flag value of the exchange private key protected through the data
protection
api.
}

I have also reverse engineered large part of the protection mechanism used
by the data protection api, but actually I have no time to put it all
and write it down.


In "myCSP" private keys operations and storage use a naïve and simple
interface which actually has two different implementations, one for W2K
files and one for NT/W95 registry and Protected Storage private key
containers format.  This interface can be used to add modules implementing
new public key cryptography operation and persistent storage type (a module
that use PKCS11 can be a useful example). There is no documentation so if
you want to understand how it works you will need to take a look at the
source
code. Actually "myCSP" uses SSLeay 0.90b as the cryptographic engine but I
think that can be replaced by OpenSSL without any problem. To test it I
have
realized a program "patchadvapi" that automatically patch the advapi32.dll,
it can also be used to sign and register the CSP. Here is a brief
description of how it works.

=======Patch Advapi=========
The advapi32.dll has two hardcoded public keys, the first key is used to
verify the signature of the CSP it needs to load, the second one is used
only if the first verification process  fails, the second key has a bad
reputation and is known as the NSAKEY. MS has publicly stated that they
never used the _NSAKEY to sign any CSP. The method I used to let
advapi32.dll load myCSP and successfully verify it is to substitute the
_NSAKEY with one self generated and then use it to sign the myCSP binary
image.  To use it you need an RSA key pair, you can use the
openSSL genrsa program to generate it. You can also use this program to
sign and register the CSP.

-advapi file : advapi32 dll file You want to patch,
-key file : openSSL RSA private key - PEM format
-register file : register and sign the CSP dll
-default : Set as default provider, be aware that if you register the CSP
as
the default provider and if the advapi32 can't verify it or the CSP does
not
work properly, your W2K system will become unuseable
-imagepath file : Path where you plan to copy the CSP dll
-provname name : Name of the CSP provider

======License and source code=======
Source code will be distributed under an openSSL style license. Actually
everyone can request source code by emailing me at [EMAIL PROTECTED],
description
of your interest and comments will be appreciated.

Sergio Tabanelli



______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    [EMAIL PROTECTED]
Automated List Manager                           [EMAIL PROTECTED]


Reply via email to