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]