summaryrefslogtreecommitdiff
path: root/src/lib/libssl/src/doc/ms3-ca.doc
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libssl/src/doc/ms3-ca.doc')
-rw-r--r--src/lib/libssl/src/doc/ms3-ca.doc398
1 files changed, 398 insertions, 0 deletions
diff --git a/src/lib/libssl/src/doc/ms3-ca.doc b/src/lib/libssl/src/doc/ms3-ca.doc
new file mode 100644
index 0000000000..f8350aadc2
--- /dev/null
+++ b/src/lib/libssl/src/doc/ms3-ca.doc
@@ -0,0 +1,398 @@
1Date: Mon, 9 Jun 97 08:00:33 +0200
2From: Holger.Reif@PrakInf.TU-Ilmenau.DE (Holger Reif)
3Subject: ms3-ca.doc
4Organization: TU Ilmenau, Fak. IA, FG Telematik
5Content-Length: 14575
6Status: RO
7X-Status:
8
9Loading client certs into MSIE 3.01
10===================================
11
12This document conatains all the information necessary to succesfully set up
13some scripts to issue client certs to Microsoft Internet Explorer. It
14includes the required knowledge about the model MSIE uses for client
15certification and includes complete sample scripts ready to play with. The
16scripts were tested against a modified ca program of SSLeay 0.6.6 and should
17work with the regular ca program that comes with version 0.8.0. I haven't
18tested against MSIE 4.0
19
20You can use the information contained in this document in either way you
21want. However if you feel it saved you a lot of time I ask you to be as fair
22as to mention my name: Holger Reif <reif@prakinf.tu-ilmenau.de>.
23
241.) The model used by MSIE
25--------------------------
26
27The Internet Explorer doesn't come with a embedded engine for installing
28client certs like Netscape's Navigator. It rather uses the CryptoAPI (CAPI)
29defined by Microsoft. CAPI comes with WindowsNT 4.0 or is installed together
30with Internet Explorer since 3.01. The advantage of this approach is a higher
31flexibility because the certificates in the (per user) system open
32certificate store may be used by other applications as well. The drawback
33however is that you need to do a bit more work to get a client cert issued.
34
35CAPI defines functions which will handle basic cryptographic work, eg.
36generating keys, encrypting some data, signing text or building a certificate
37request. The procedure is as follows: A CAPI function generates you a key
38pair and saves it into the certificate store. After that one builds a
39Distinguished Name. Together with that key pair another CAPI function forms a
40PKCS#10 request which you somehow need to submit to a CA. Finally the issued
41cert is given to a yet another CAPI function which saves it into the
42certificate store.
43
44The certificate store with the user's keys and certs is in the registry. You
45will find it under HKEY_CURRENT_USER/Software/Microsoft/Cryptography/ (I
46leave it to you as a little exercise to figure out what all the entries mean
47;-). Note that the keys are protected only with the user's usual Windows
48login password.
49
502.) The practical usage
51-----------------------
52
53Unfortunatly since CAPI is a system API you can't access its functions from
54HTML code directly. For this purpose Microsoft provides a wrapper called
55certenr3.dll. This DLL accesses the CAPI functions and provides an interface
56usable from Visual Basic Script. One needs to install that library on the
57computer which wants to have client cert. The easiest way is to load it as an
58ActiveX control (certenr3.dll is properly authenticode signed by MS ;-). If
59you have ever enrolled e cert request at a CA you will have installed it.
60
61At time of writing certenr3.dll is contained in
62http://www.microsoft.com/workshop/prog/security/csa/certenr3.exe. It comes
63with an README file which explains the available functions. It is labeled
64beta but every CA seems to use it anyway. The license.txt allows you the
65usage for your own purposes (as far as I understood) and a somehow limited
66distribution.
67
68The two functions of main interest are GenerateKeyPair and AcceptCredentials.
69For complete explanation of all possible parameters see the README file. Here
70are only minimal required parameters and their values.
71
72GenerateKeyPair(sessionID, FASLE, szName, 0, "ClientAuth", TRUE, FALSE, 1)
73- sessionID is a (locally to that computer) unique string to correlate the
74generated key pair with a cert installed later.
75- szName is the DN of the form "C=DE; S=Thueringen; L=Ilmenau; CN=Holger
76Reif; 1.2.840.113549.1.9.1=reif@prakinf.tu-ilmenau.de". Note that S is the
77abreviation for StateOrProvince. The recognized abreviation include CN, O, C,
78OU, G, I, L, S, T. If the abreviation is unknown (eg. for PKCS#9 email addr)
79you need to use the full object identifier. The starting point for searching
80them could be crypto/objects.h since all OIDs know to SSLeay are listed
81there.
82- note: the possible ninth parameter which should give a default name to the
83certificate storage location doesn't seem to work. Changes to the constant
84values in the call above doesn't seem to make sense. You can't generate
85PKCS#10 extensions with that function.
86
87The result of GenerateKeyPair is the base64 encoded PKCS#10 request. However
88it has a little strange format that SSLeay doesn't accept. (BTW I feel the
89decision of rejecting that format as standard conforming.) It looks like
90follows:
91 1st line with 76 chars
92 2nd line with 76 chars
93 ...
94 (n-2)th line with 76 chars
95 (n-1)th line contains a multiple of 4 chars less then 76 (possible
96empty)
97 (n)th line has zero or 4 chars (then with 1 or 2 equal signs - the
98 original text's lenght wasn'T a multiple of 3)
99 The line separator has two chars: 0x0d 0x0a
100
101AcceptCredentials(sessionID, credentials, 0, FALSE)
102- sessionID needs to be the same as while generating the key pair
103- credentials is the base64 encoded PKCS#7 object containing the cert.
104
105CRL's and CA certs are not required simply just the client cert. (It seems to
106me that both are not even checked somehow.) The only format of the base64
107encoded object I succesfully used was all characters in a very long string
108without line feeds or carriage returns. (Hey, it doesn't matter, only a
109computer reads it!)
110
111The result should be S_OK. For error handling see the example that comes with
112certenr3.dll.
113
114A note about ASN.1 character encodings. certenr3.dll seems to know only about
1152 of them: UniversalString and PrintableString. First it is definitely wrong
116for an email address which is IA5STRING (checked by ssleay's ca). Second
117unfortunately MSIE (at least until version 3.02) can't handle UniversalString
118correctly - they just blow up you cert store! Therefore ssleay's ca (starting
119from version 0.8.0) tries to convert the encodings automatically to IA5STRING
120or TeletexString. The beef is it will work only for the latin-1 (western)
121charset. Microsoft still has to do abit of homework...
122
1233.) An example
124--------------
125
126At least you need two steps: generating the key & request and then installing
127the certificate. A real world CA would have some more steps involved, eg.
128accepting some license. Note that both scripts shown below are just
129experimental state without any warrenty!
130
131First how to generate a request. Note that we can't use a static page because
132of the sessionID. I generate it from system time plus pid and hope it is
133unique enough. Your are free to feed it through md5 to get more impressive
134ID's ;-) Then the intended text is read in with sed which inserts the
135sessionID.
136
137-----BEGIN ms-enroll.cgi-----
138#!/bin/sh
139SESSION_ID=`date '+%y%m%d%H%M%S'`$$
140echo Content-type: text/html
141echo
142sed s/template_for_sessId/$SESSION_ID/ <<EOF
143<HTML><HEAD>
144<TITLE>Certificate Enrollment Test Page</TITLE>
145</HEAD><BODY>
146
147<OBJECT
148 classid="clsid:33BEC9E0-F78F-11cf-B782-00C04FD7BF43"
149 codebase=certenr3.dll
150 id=certHelper
151 >
152</OBJECT>
153
154<CENTER>
155<H2>enrollment for a personal cert</H2>
156<BR><HR WIDTH=50%><BR><P>
157<FORM NAME="MSIE_Enrollment" ACTION="ms-gencert.cgi" ENCTYPE=x-www-form-
158encoded METHOD=POST>
159<TABLE>
160 <TR><TD>Country</TD><TD><INPUT NAME="Country" VALUE=""></TD></TR>
161 <TR><TD>State</TD><TD><INPUT NAME="StateOrProvince" VALUE=""></TD></TR>
162 <TR><TD>Location</TD><TD><INPUT NAME="Location" VALUE=""></TD></TR>
163 <TR><TD>Organization</TD><TD><INPUT NAME="Organization"
164VALUE=""></TD></TR>
165 <TR><TD>Organizational Unit</TD>
166 <TD><INPUT NAME="OrganizationalUnit" VALUE=""></TD></TR>
167 <TR><TD>Name</TD><TD><INPUT NAME="CommonName" VALUE=""></TD></TR>
168 <TR><TD>eMail Address</TD>
169 <TD><INPUT NAME="EmailAddress" VALUE=""></TD></TR>
170 <TR><TD></TD>
171 <TD><INPUT TYPE="BUTTON" NAME="submit" VALUE="Beantragen"></TD></TR>
172</TABLE>
173 <INPUT TYPE="hidden" NAME="SessionId" VALUE="template_for_sessId">
174 <INPUT TYPE="hidden" NAME="Request" VALUE="">
175</FORM>
176<BR><HR WIDTH=50%><BR><P>
177</CENTER>
178
179<SCRIPT LANGUAGE=VBS>
180 Dim DN
181
182 Sub Submit_OnClick
183 Dim TheForm
184 Set TheForm = Document.MSIE_Enrollment
185 sessionId = TheForm.SessionId.value
186 reqHardware = FALSE
187 C = TheForm.Country.value
188 SP = TheForm.StateOrProvince.value
189 L = TheForm.Location.value
190 O = TheForm.Organization.value
191 OU = TheForm.OrganizationalUnit.value
192 CN = TheForm.CommonName.value
193 Email = TheForm.EmailAddress.value
194 szPurpose = "ClientAuth"
195 doAcceptanceUINow = FALSE
196 doOnline = TRUE
197
198 DN = ""
199
200 Call Add_RDN("C", C)
201 Call Add_RDN("S", SP)
202 Call Add_RDN("L", L)
203 Call Add_RDN("O", O)
204 Call Add_RDN("OU", OU)
205 Call Add_RDN("CN", CN)
206 Call Add_RDN("1.2.840.113549.1.9.1", Email)
207 ' rsadsi
208 ' pkcs
209 ' pkcs9
210 ' eMailAddress
211 On Error Resume Next
212 sz10 = certHelper.GenerateKeyPair(sessionId, _
213 FALSE, DN, 0, ClientAuth, FASLE, TRUE, 1)_
214 theError = Err.Number
215 On Error Goto 0
216 if (sz10 = Empty OR theError <> 0) Then
217 sz = "The error '" & Hex(theError) & "' occurred." & chr(13) & _
218 chr(10) & "Your credentials could not be generated."
219 result = MsgBox(sz, 0, "Credentials Enrollment")
220 Exit Sub
221 else
222 TheForm.Request.value = sz10
223 TheForm.Submit
224 end if
225 End Sub
226
227 Sub Add_RDN(sn, value)
228 if (value <> "") then
229 if (DN <> "") then
230 DN = DN & "; "
231 end if
232 DN = DN & sn & "=" & value
233 end if
234 End Sub
235</SCRIPT>
236</BODY>
237</HTML>
238EOF
239-----END ms-enroll.cgi-----
240
241Second, how to extract the request and feed the certificate back? We need to
242"normalize" the base64 encoding of the PKCS#10 format which means
243regenerating the lines and wrapping with BEGIN and END line. This is done by
244gawk. The request is taken by ca the normal way. Then the cert needs to be
245packed into a PKCS#7 structure (note: the use of a CRL is necessary for
246crl2pkcs7 as of version 0.6.6. Starting with 0.8.0 it it might probably be
247ommited). Finally we need to format the PKCS#7 object and generate the HTML
248text. I use two templates to have a clearer script.
249
2501st note: postit2 is slightly modified from a program I found at ncsa's ftp
251site. Grab it from http://www.easterngraphics.com/certs/IX9704/postit2.c. You
252need utils.c from there too.
253
2542nd note: I'm note quite sure wether the gawk script really handles all
255possible inputs for the request right! Today I don't use this construction
256anymore myself.
257
2583d note: the cert must be of version 3! This could be done with the nsComment
259line in ssleay.cnf...
260
261------BEGIN ms-gencert.cgi-----
262#!/bin/sh
263FILE="/tmp/"`date '+%y%m%d%H%M%S'-`$$
264rm -f "$FILE".*
265
266HOME=`pwd`; export HOME # as ssleay.cnf insists on having such an env var
267cd /usr/local/ssl #where demoCA (as named in ssleay.conf) is located
268
269postit2 -s " " -i 0x0d > "$FILE".inp # process the FORM vars
270
271SESSION_ID=`gawk '$1 == "SessionId" { print $2; exit }' "$FILE".inp`
272
273gawk \
274 'BEGIN { \
275 OFS = ""; \
276 print "-----BEGIN CERTIFICATE REQUEST-----"; \
277 req_seen=0 \
278 } \
279 $1 == "Request" { \
280 req_seen=1; \
281 if (length($2) == 72) print($2); \
282 lastline=$2; \
283 next; \
284 } \
285 { \
286 if (req_seen == 1) { \
287 if (length($1) >= 72) print($1); \
288 else if (length(lastline) < 72) { \
289 req_seen=0; \
290 print (lastline,$1); \
291 } \
292 lastline=$1; \
293 } \
294 } \
295 END { \
296 print "-----END CERTIFICATE REQUEST-----"; \
297 }' > "$FILE".pem < "$FILE".inp
298
299ssleay ca -batch -in "$FILE".pem -key passwd -out "$FILE".out
300ssleay crl2pkcs7 -certfile "$FILE".out -out "$FILE".pkcs7 -in demoCA/crl.pem
301
302sed s/template_for_sessId/$SESSION_ID/ <ms-enroll2a.html >"$FILE".cert
303/usr/local/bin/gawk \
304 'BEGIN { \
305 OFS = ""; \
306 dq = sprintf("%c",34); \
307 } \
308 $0 ~ "PKCS7" { next; } \
309 { \
310 print dq$0dq" & _"; \
311 }' <"$FILE".pkcs7 >> "$FILE".cert
312cat ms-enroll2b.html >>"$FILE".cert
313
314echo Content-type: text/html
315echo Content-length: `wc -c "$FILE".cert`
316echo
317cat "$FILE".cert
318rm -f "$FILE".*
319-----END ms-gencert.cgi-----
320
321----BEGIN ms-enroll2a.html----
322<HTML><HEAD><TITLE>Certificate Acceptance Test Page</TITLE></HEAD><BODY>
323
324<OBJECT
325 classid="clsid:33BEC9E0-F78F-11cf-B782-00C04FD7BF43"
326 codebase=certenr3.dll
327 id=certHelper
328 >
329</OBJECT>
330
331<CENTER>
332<H2>Your personal certificate</H2>
333<BR><HR WIDTH=50%><BR><P>
334Press the button!
335<P><INPUT TYPE=BUTTON VALUE="Nimm mich!" NAME="InstallCert">
336</CENTER>
337<BR><HR WIDTH=50%><BR>
338
339<SCRIPT LANGUAGE=VBS>
340 Sub InstallCert_OnClick
341
342 sessionId = "template_for_sessId"
343credentials = "" & _
344----END ms-enroll2a.html----
345
346----BEGIN ms-enroll2b.html----
347""
348 On Error Resume Next
349 result = certHelper.AcceptCredentials(sessionId, credentials, 0,
350FALSE)
351 if (IsEmpty(result)) Then
352 sz = "The error '" & Err.Number & "' occurred." & chr(13) &
353chr(10) & "This Digital ID could not be registered."
354 msgOut = MsgBox(sz, 0, "Credentials Registration Error")
355 navigate "error.html"
356 else
357 sz = "Digital ID successfully registered."
358 msgOut = MsgBox(sz, 0, "Credentials Registration")
359 navigate "success.html"
360 end if
361 Exit Sub
362 End Sub
363</SCRIPT>
364</BODY>
365</HTML>
366----END ms-enroll2b.html----
367
3684.) What do do with the cert?
369-----------------------------
370
371The cert is visible (without restarting MSIE) under the following menu:
372View->Options->Security->Personal certs. You can examine it's contents at
373least partially.
374
375To use it for client authentication you need to use SSL3.0 (fortunately
376SSLeay supports it with 0.8.0). Furthermore MSIE is told to only supports a
377kind of automatic selection of certs (I personally wasn't able to test it
378myself). But there is a requirement that the issuer of the server cert and
379the issuer of the client cert needs to be the same (according to a developer
380from MS). Which means: you need may more then one cert to talk to all
381servers...
382
383I'm sure we will get a bit more experience after ApacheSSL is available for
384SSLeay 0.8.8.
385
386
387I hope you enjoyed reading and that in future questions on this topic will
388rarely appear on ssl-users@moncom.com ;-)
389
390Ilmenau, 9th of June 1997
391Holger Reif <reif@prakinf.tu-ilmenau.de>
392--
393read you later - Holger Reif
394---------------------------------------- Signaturprojekt Deutsche Einheit
395TU Ilmenau - Informatik - Telematik (Verdamp lang her)
396Holger.Reif@PrakInf.TU-Ilmenau.DE Alt wie ein Baum werden, um ueber
397http://Remus.PrakInf.TU-Ilmenau.DE/Reif/ alle 7 Bruecken gehen zu koennen
398