Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / New Users / October 2007

Tip: Looking for answers? Try searching our database.

CspParameter and CryptSetProvParam(PP_KEYEXCHANGE_PIN)

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
John Allberg - 19 Sep 2007 08:38 GMT
Hi!

I recently had to create an application using smart card certificates, but
since this was going to be a server application we had to insert the smart
card pin from the software.

So, I embarked on a mission to use P/Invoke but realized there is a
CspParameter constructor that takes a password, CspParameters (Int32,
String, String, CryptoKeySecurity, SecureString).

Happy as a bird I created a test app, but it didn't work, throwing an
System.Security.Cryptography.CryptographicException ("Cannot create a file
when that file already exists.") . (Thats obviously a generic "Access
Denied"-message)

When investigating, I saw in the CSP log that it receives only one character
of the password in the native CryptSetProvParam(PP_KEYEXCHANGE_PIN) and
therefore returns an error. It turns out that the password that I supplied
in the CspParameter constructor is formatted with unicode when arriving to
the CSP which in turn thinks it should be a null-terminated ascii.string and
since it found a null byte in position 2 it ended there, receiving only the
first character.

I throw that info at the CSP manufacturer and what I got back was this
reference to MSDN:

http://msdn2.microsoft.com/en-us/library/aa380276.aspx

That clearly states (for the PP_KEYEXCHANGE_PIN parameter) "The PIN is
represented as a null-terminated ASCII string." so giving that in Unicode as
CspParameter does is right out wrong.

Anyone else that can confirm this bad behaviour of CspParameter with
password?

Regards,

John Allberg

The exception:

System.Security.Cryptography.CryptographicException: Cannot create a file
when that file already exists.

  at
System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(Int32
hr)

  at
System.Security.Cryptography.Utils._SetProviderParameter(SafeProvHandle
hProv, Int32 keyNumber, UInt32 paramID, IntPtr pbData)

  at System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType
keyType, CspParameters parameters, Boolean randomKeyContainer, Int32
dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle)

  at System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair()

  at System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32
dwKeySize, CspParameters parameters, Boolean useDefaultKeySize)

  at
System.Security.Cryptography.RSACryptoServiceProvider..ctor(CspParameters
parameters)

  at ConsoleApplication1.UseCapiCom.Run() in C:\Visual Studio
Projects\TestSmartCardPIN\ConsoleApplication1\UseCapiCom.cs

The code:

CAPICOM.StoreClass store = new CAPICOM.StoreClass();
store.Open(CAPICOM.CAPICOM_STORE_LOCATION.CAPICOM_CURRENT_USER_STORE, "MY",

   CAPICOM.CAPICOM_STORE_OPEN_MODE.CAPICOM_STORE_OPEN_EXISTING_ONLY |

   CAPICOM.CAPICOM_STORE_OPEN_MODE.CAPICOM_STORE_OPEN_READ_ONLY);

CAPICOM.ICertificates2 storeCerts =
(CAPICOM.ICertificates2)store.Certificates;

CAPICOM.ICertificates2 certs =

   storeCerts.Find(CAPICOM.CAPICOM_CERTIFICATE_FIND_TYPE.CAPICOM_CERTIFICATE_FIND_SHA1_HASH,

   "a7 0d e7 7a 97 c3 24 8f 8b 80 17 d6 23 9a 43 0d 8c 8c 06 b1", false);

CAPICOM.ICertificate2 cert = (CAPICOM.ICertificate2)certs[1];
Console.WriteLine("Found cert with following CSP data: ");

Console.WriteLine("ProviderType: " + (int)cert.PrivateKey.ProviderType);

Console.WriteLine("ProviderName: " + cert.PrivateKey.ProviderName);

Console.WriteLine("ContainerName: " + cert.PrivateKey.ContainerName);

char[] pwdChars = "123456".ToCharArray(); System.Security.SecureString pwd =
new System.Security.SecureString(); pwd.Clear(); foreach (char chr in
pwdChars) pwd.AppendChar(chr);

System.Security.AccessControl.CryptoKeySecurity keySec =

   new System.Security.AccessControl.CryptoKeySecurity();

int provType = (int)cert.PrivateKey.ProviderType;

CspParameters csp = new CspParameters(provType,
cert.PrivateKey.ProviderName, cert.PrivateKey.ContainerName, new
System.Security.AccessControl.CryptoKeySecurity(), pwd); try {

   Console.WriteLine("Creating RSACryptoServiceProvider()...");

   RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(csp); //
this is what throws the exc

   Console.WriteLine("Signing RSACryptoServiceProvider()...");

   byte[] signature = rsa.SignData(

       System.Text.UnicodeEncoding.Unicode.GetBytes("DataToBeSigned"),

       new SHA1Managed());

   Console.WriteLine(Convert.ToBase64String(signature));

}

catch (Exception exc)

{

   Console.WriteLine(exc.ToString());

}
Walter Wang [MSFT] - 19 Sep 2007 11:35 GMT
Hi John,

Welcome to MSDN Managed Newsgroup!

Please feel free to correct me if I've misunderstood anything.

To convert the SecureString in CspParameters to ANSI and pass to
CryptSetProvParam, you can use Marshal.SecureStringToCoTaskMemAnsi:

http://msdn2.microsoft.com/en-us/library/system.runtime.interopservices.mars
hal.securestringtocotaskmemansi.aspx

It will return an IntPtr, you need to declare CryptSetProvParam's third
parameter as IntPtr and pass this in.

Enclose the call within try/finally block, in finally block, call
Marshal.ZeroFreeCoTaskMemAnsi to release the IntPtr.

Please post your complete code listing if this suggestion doesn't help.
Thanks.

Sincerely,
Walter Wang (wawang@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
For MSDN subscribers whose posts are left unanswered, please check this
document: http://blogs.msdn.com/msdnts/pages/postingAlias.aspx

Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications. If you are using Outlook Express/Windows Mail, please make sure
you clear the check box "Tools/Options/Read: Get 300 headers at a time" to
see your reply promptly.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
John Allberg - 20 Sep 2007 08:58 GMT
Hi Walter!

I think you misunderstood what I was trying to say. I boldy state that the
framwork class "CspParameters" with the constructor

CspParameters (Int32, String, String, CryptoKeySecurity, SecureString)

is flawed since it calls the CryptSetProvParam function with the content of
the above SecureString encoded in unicode instead of ascii as the MSDN docs
of CryptSetProvParam states it should. Could you please verify this?

I couldn't even get it to work with MS CSP, but I'm not as familiar with
reading any logs from MS CSP as the one I'm using ("Net iD - CSP").

I have managed to work around this problem with importing CryptSetProvParam,
much the way you suggested, but I thought I call out if somebody else could
verify my finding and perhaps even get MS to fix the problem...

Regards,

John

> Hi John,
>
[quoted text clipped - 46 lines]
> This posting is provided "AS IS" with no warranties, and confers no
> rights.
Walter Wang [MSFT] - 20 Sep 2007 12:21 GMT
Hi John,

Thanks for your quick update and sorry for my misunderstanding.

Well, I searched our internal database and did find some fixed bug that was
using Unicode instead of ANSI for the password. However, I just verified
using Reflector (http://www.aisto.com/roeder/dotnet/) that my .NET 2.0 on  
Vista has already incorporated the fix.

My %windir%\microsoft.net\framework\v2.0.50727\mscorlib.dll has version
2.0.50727.1378, size 4,399,104 bytes. Would you please check yours and see
if it has the same version?

If you're already having newest version, would you please post your code
which could reproduce the issue you mentioned? Thanks.

Regards,
Walter Wang (wawang@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
John Allberg - 20 Sep 2007 14:10 GMT
Hi Walter,

thanks for your quick reply.

My version was 2.0.50727.832 so I'm obiously some steps behind. It seems the
2.0.50727.832 came from MS07-040.

I checked with MicrosoftUpdate but couldn't find an update so I went to MSDN
and couldn't find one there either.

According to
http://blogs.msdn.com/dougste/archive/2007/07/31/summary-of-fixes-available-for-
asp-net-2-0.aspx

the 2.0.50727.1378 version isn't even a released hotfix. I don't like the
thought of installing .Net framework 3.5 beta, do you know if there are any
fixes to download separatly?

Regards,

John
Walter Wang [MSFT] - 21 Sep 2007 04:26 GMT
Hi John,

I've just verified that the issue does get fixed in 2.0.50727.1378 but not
in 2.0.50727.832. Here's the relevant code extracted using Reflector
(http://www.aisto.com/roeder/dotnet/):

mscorlib.dll

System.Security.Cryptography.Utils

internal static void GetKeyPairHelper(CspAlgorithmType keyType,
CspParameters parameters, bool randomKeyContainer, int dwKeySize, ref
SafeProvHandle safeProvHandle, ref SafeKeyHandle safeKeyHandle)

2.0.50727.832:

   else if (parameters.KeyPassword != null)
   {
       IntPtr pbData =
X509Utils.PasswordToCoTaskMemUni(parameters.KeyPassword);
       try
       {
           _SetProviderParameter(hProv, parameters.KeyNumber, 11, pbData);
       }
       finally
       {
           if (pbData != IntPtr.Zero)
           {
               Marshal.ZeroFreeCoTaskMemUnicode(pbData);
           }
       }
   }

2.0.50727.1378

   else if (parameters.KeyPassword != null)
   {
       IntPtr pbData =
Marshal.SecureStringToCoTaskMemAnsi(parameters.KeyPassword);
       try
       {
           _SetProviderParameter(hProv, parameters.KeyNumber, 11, pbData);
       }
       finally
       {
           if (pbData != IntPtr.Zero)
           {
               Marshal.ZeroFreeCoTaskMemAnsi(pbData);
           }
       }
   }

Sorry for the inconvenience caused.

I cannot seem to find dedicated kb or hotfix to describe this change. As
far as I know we don't have a separate update to update the mscorlib.dll to
version 1378, but I will ask around to see if there's anything I missed.
I'll keep you posted.

Regards,
Walter Wang (wawang@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
John Allberg - 21 Sep 2007 08:46 GMT
Hi Walter,

thank you for your answer, reflector is very usable... :-)

Do you think I should open a support issue for this to get a packaged hotfix?

Regards,

John
Walter Wang [MSFT] - 21 Sep 2007 09:36 GMT
Hi John,

So far I haven't found an existing hotfix for this to upgrade standalone
.NET 2.0 framework. Please go ahead to open a support incident to request
the hotfix. Our CSS (Customer Support and Service) will decide whether or
not to provide a hotfix for you based on your business impact. (For such
confirmed issue of our product, the support incident will be free). You can
refer to this newsgroup thread or me when contacting CSS.

Please feel free to let me know if there's anything else I can help. Thanks.

Regards,
Walter Wang (wawang@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
Walter Wang [MSFT] - 21 Sep 2007 10:18 GMT
Hi John,

Just after I posted my last reply, I got updated information that we're
actually having a hotfix for this issue and preparing to publish a KB.
Please email me and I will let you know the KB ID so that you could more
easily request the hotfix. (Sorry I cannot state the KB ID here publicly
before it's published to avoid confusion).

Regards,
Walter Wang (wawang@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
Dan_Phillips - 13 Oct 2007 14:07 GMT
Walter,
We are experiencing a similar problem with the cspparameters method and the
keypassword parameter.
We are using a smartcard and trying to read the cert from the card and the
pass the password to the card thus avoiding having the login dialog appear
prompting for the password.

We are using c# to pass a secure string to the csppararameters keypassword
parameter and are are getting a mesage back that our password is incorrect.
We are sure the password is correct and have found other developers who have
found the same problem.

           // To idendify the Smart Card CryptoGraphic Providers on your
           // computer, use the Microsoft Registry Editor (Regedit.exe).
           // The available Smart Card CryptoGraphic Providers are listed
           // in HKEY_LOCAL_MACHINE\Software\Microsoft\Cryptography\Defaults\
Provider.

       
           // Create a new CspParameters object that identifies a
           // Smart Card CryptoGraphic Provider.

           CspParameters cspp = new CspParameters(1, "Datakey RSA CSP");

           System.Security.SecureString sss = new System.Security.
SecureString();
           sss.AppendChar('1');
           sss.AppendChar('2');
           sss.AppendChar('3');
           sss.AppendChar('4');

           cspp.KeyPassword = sss;
           cspp.Flags = CspProviderFlags.UseDefaultKeyContainer;

           RSACryptoServiceProvider rsaa = new RSACryptoServiceProvider(cspp)
;

Error occurs here.  If we remove the cspp.KeyPassword  = sss; line the code
prompts us for the password and the rest of the code works fine.

From the sounds of this thread John is experiencing the same problem.  Can we
ge the hot fix also as we have the 2.0.50727.832 version of the mscorlib.dll
file.

Your help would be greatly appreciated as we have been trying to get this
fixed for sometime.

Thanks in advance

Dan Phillips
dphillips210 (at) aol.com

>Hi John,
>
[quoted text clipped - 14 lines]
>
>This posting is provided "AS IS" with no warranties, and confers no rights.

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.