Date: Mon, 9 Jun 97 08:00:33 +0200 From: Holger.Reif@PrakInf.TU-Ilmenau.DE (Holger Reif) Subject: ms3-ca.doc Organization: TU Ilmenau, Fak. IA, FG Telematik Content-Length: 14575 Status: RO X-Status: Loading client certs into MSIE 3.01 =================================== This document conatains all the information necessary to succesfully set up some scripts to issue client certs to Microsoft Internet Explorer. It includes the required knowledge about the model MSIE uses for client certification and includes complete sample scripts ready to play with. The scripts were tested against a modified ca program of SSLeay 0.6.6 and should work with the regular ca program that comes with version 0.8.0. I haven't tested against MSIE 4.0 You can use the information contained in this document in either way you want. However if you feel it saved you a lot of time I ask you to be as fair as to mention my name: Holger Reif . 1.) The model used by MSIE -------------------------- The Internet Explorer doesn't come with a embedded engine for installing client certs like Netscape's Navigator. It rather uses the CryptoAPI (CAPI) defined by Microsoft. CAPI comes with WindowsNT 4.0 or is installed together with Internet Explorer since 3.01. The advantage of this approach is a higher flexibility because the certificates in the (per user) system open certificate store may be used by other applications as well. The drawback however is that you need to do a bit more work to get a client cert issued. CAPI defines functions which will handle basic cryptographic work, eg. generating keys, encrypting some data, signing text or building a certificate request. The procedure is as follows: A CAPI function generates you a key pair and saves it into the certificate store. After that one builds a Distinguished Name. Together with that key pair another CAPI function forms a PKCS#10 request which you somehow need to submit to a CA. Finally the issued cert is given to a yet another CAPI function which saves it into the certificate store. The certificate store with the user's keys and certs is in the registry. You will find it under HKEY_CURRENT_USER/Software/Microsoft/Cryptography/ (I leave it to you as a little exercise to figure out what all the entries mean ;-). Note that the keys are protected only with the user's usual Windows login password. 2.) The practical usage ----------------------- Unfortunatly since CAPI is a system API you can't access its functions from HTML code directly. For this purpose Microsoft provides a wrapper called certenr3.dll. This DLL accesses the CAPI functions and provides an interface usable from Visual Basic Script. One needs to install that library on the computer which wants to have client cert. The easiest way is to load it as an ActiveX control (certenr3.dll is properly authenticode signed by MS ;-). If you have ever enrolled e cert request at a CA you will have installed it. At time of writing certenr3.dll is contained in http://www.microsoft.com/workshop/prog/security/csa/certenr3.exe. It comes with an README file which explains the available functions. It is labeled beta but every CA seems to use it anyway. The license.txt allows you the usage for your own purposes (as far as I understood) and a somehow limited distribution. The two functions of main interest are GenerateKeyPair and AcceptCredentials. For complete explanation of all possible parameters see the README file. Here are only minimal required parameters and their values. GenerateKeyPair(sessionID, FASLE, szName, 0, "ClientAuth", TRUE, FALSE, 1) - sessionID is a (locally to that computer) unique string to correlate the generated key pair with a cert installed later. - szName is the DN of the form "C=DE; S=Thueringen; L=Ilmenau; CN=Holger Reif; 1.2.840.113549.1.9.1=reif@prakinf.tu-ilmenau.de". Note that S is the abreviation for StateOrProvince. The recognized abreviation include CN, O, C, OU, G, I, L, S, T. If the abreviation is unknown (eg. for PKCS#9 email addr) you need to use the full object identifier. The starting point for searching them could be crypto/objects.h since all OIDs know to SSLeay are listed there. - note: the possible ninth parameter which should give a default name to the certificate storage location doesn't seem to work. Changes to the constant values in the call above doesn't seem to make sense. You can't generate PKCS#10 extensions with that function. The result of GenerateKeyPair is the base64 encoded PKCS#10 request. However it has a little strange format that SSLeay doesn't accept. (BTW I feel the decision of rejecting that format as standard conforming.) It looks like follows: 1st line with 76 chars 2nd line with 76 chars ... (n-2)th line with 76 chars (n-1)th line contains a multiple of 4 chars less then 76 (possible empty) (n)th line has zero or 4 chars (then with 1 or 2 equal signs - the original text's lenght wasn'T a multiple of 3) The line separator has two chars: 0x0d 0x0a AcceptCredentials(sessionID, credentials, 0, FALSE) - sessionID needs to be the same as while generating the key pair - credentials is the base64 encoded PKCS#7 object containing the cert. CRL's and CA certs are not required simply just the client cert. (It seems to me that both are not even checked somehow.) The only format of the base64 encoded object I succesfully used was all characters in a very long string without line feeds or carriage returns. (Hey, it doesn't matter, only a computer reads it!) The result should be S_OK. For error handling see the example that comes with certenr3.dll. A note about ASN.1 character encodings. certenr3.dll seems to know only about 2 of them: UniversalString and PrintableString. First it is definitely wrong for an email address which is IA5STRING (checked by ssleay's ca). Second unfortunately MSIE (at least until version 3.02) can't handle UniversalString correctly - they just blow up you cert store! Therefore ssleay's ca (starting from version 0.8.0) tries to convert the encodings automatically to IA5STRING or TeletexString. The beef is it will work only for the latin-1 (western) charset. Microsoft still has to do abit of homework... 3.) An example -------------- At least you need two steps: generating the key & request and then installing the certificate. A real world CA would have some more steps involved, eg. accepting some license. Note that both scripts shown below are just experimental state without any warrenty! First how to generate a request. Note that we can't use a static page because of the sessionID. I generate it from system time plus pid and hope it is unique enough. Your are free to feed it through md5 to get more impressive ID's ;-) Then the intended text is read in with sed which inserts the sessionID. -----BEGIN ms-enroll.cgi----- #!/bin/sh SESSION_ID=`date '+%y%m%d%H%M%S'`$$ echo Content-type: text/html echo sed s/template_for_sessId/$SESSION_ID/ < Certificate Enrollment Test Page

enrollment for a personal cert




Country
State
Location
Organization
Organizational Unit
Name
eMail Address



EOF -----END ms-enroll.cgi----- Second, how to extract the request and feed the certificate back? We need to "normalize" the base64 encoding of the PKCS#10 format which means regenerating the lines and wrapping with BEGIN and END line. This is done by gawk. The request is taken by ca the normal way. Then the cert needs to be packed into a PKCS#7 structure (note: the use of a CRL is necessary for crl2pkcs7 as of version 0.6.6. Starting with 0.8.0 it it might probably be ommited). Finally we need to format the PKCS#7 object and generate the HTML text. I use two templates to have a clearer script. 1st note: postit2 is slightly modified from a program I found at ncsa's ftp site. Grab it from http://www.easterngraphics.com/certs/IX9704/postit2.c. You need utils.c from there too. 2nd note: I'm note quite sure wether the gawk script really handles all possible inputs for the request right! Today I don't use this construction anymore myself. 3d note: the cert must be of version 3! This could be done with the nsComment line in ssleay.cnf... ------BEGIN ms-gencert.cgi----- #!/bin/sh FILE="/tmp/"`date '+%y%m%d%H%M%S'-`$$ rm -f "$FILE".* HOME=`pwd`; export HOME # as ssleay.cnf insists on having such an env var cd /usr/local/ssl #where demoCA (as named in ssleay.conf) is located postit2 -s " " -i 0x0d > "$FILE".inp # process the FORM vars SESSION_ID=`gawk '$1 == "SessionId" { print $2; exit }' "$FILE".inp` gawk \ 'BEGIN { \ OFS = ""; \ print "-----BEGIN CERTIFICATE REQUEST-----"; \ req_seen=0 \ } \ $1 == "Request" { \ req_seen=1; \ if (length($2) == 72) print($2); \ lastline=$2; \ next; \ } \ { \ if (req_seen == 1) { \ if (length($1) >= 72) print($1); \ else if (length(lastline) < 72) { \ req_seen=0; \ print (lastline,$1); \ } \ lastline=$1; \ } \ } \ END { \ print "-----END CERTIFICATE REQUEST-----"; \ }' > "$FILE".pem < "$FILE".inp ssleay ca -batch -in "$FILE".pem -key passwd -out "$FILE".out ssleay crl2pkcs7 -certfile "$FILE".out -out "$FILE".pkcs7 -in demoCA/crl.pem sed s/template_for_sessId/$SESSION_ID/ "$FILE".cert /usr/local/bin/gawk \ 'BEGIN { \ OFS = ""; \ dq = sprintf("%c",34); \ } \ $0 ~ "PKCS7" { next; } \ { \ print dq$0dq" & _"; \ }' <"$FILE".pkcs7 >> "$FILE".cert cat ms-enroll2b.html >>"$FILE".cert echo Content-type: text/html echo Content-length: `wc -c "$FILE".cert` echo cat "$FILE".cert rm -f "$FILE".* -----END ms-gencert.cgi----- ----BEGIN ms-enroll2a.html---- Certificate Acceptance Test Page

Your personal certificate




Press the button!




----END ms-enroll2b.html---- 4.) What do do with the cert? ----------------------------- The cert is visible (without restarting MSIE) under the following menu: View->Options->Security->Personal certs. You can examine it's contents at least partially. To use it for client authentication you need to use SSL3.0 (fortunately SSLeay supports it with 0.8.0). Furthermore MSIE is told to only supports a kind of automatic selection of certs (I personally wasn't able to test it myself). But there is a requirement that the issuer of the server cert and the issuer of the client cert needs to be the same (according to a developer from MS). Which means: you need may more then one cert to talk to all servers... I'm sure we will get a bit more experience after ApacheSSL is available for SSLeay 0.8.8. I hope you enjoyed reading and that in future questions on this topic will rarely appear on ssl-users@moncom.com ;-) Ilmenau, 9th of June 1997 Holger Reif -- read you later - Holger Reif ---------------------------------------- Signaturprojekt Deutsche Einheit TU Ilmenau - Informatik - Telematik (Verdamp lang her) Holger.Reif@PrakInf.TU-Ilmenau.DE Alt wie ein Baum werden, um ueber http://Remus.PrakInf.TU-Ilmenau.DE/Reif/ alle 7 Bruecken gehen zu koennen