Sunday, July 17, 2005

How to setup a CA of your own

In my efforts to implement a secure wireless LAN, utilizing RADIUS based authentication, I had quick success on username/password based authentication, but we had considerable difficulty getting X.509 certificate based authentication because we were not very well versed on it. Finally I managed to get it done. Here is how. Please know that some of the links would not work because I have not uploaded the files to my web server yet. Please be patient, I'll upload them shortly.

Create your own Certificate Authority

One way to create your own Certificate Authority (CA) is to use the Certificate Services that come with Windows 2000 Server. Having already installed FreeRadius on RedHat Linux 9.0, I decided that we should set the CA up on Linux as well. Well, you could actually set up your RADIUS server on Windows 2000 Server also.
So, the first thing to do to set up your own CA is to install openssl. I isntalled version 0.9.7a and freeradius 2.0.
While you can set everything up in the directory where openssl is installed, this page suggests that you create a different directory structure, so that it is not affected by any OS updates etc. In my case, openssl was installed in /usr/share/ssl. I took the advice and ran the following commands on the console:

[root@localhost CA]# mkdir /CA
[root@localhost CA]# cd /CA
[root@localhost CA]# mkdir certs
[root@localhost CA]# mkdir private
[root@localhost CA]# chmod 700 private
[root@localhost CA]# echo '01' > serial
[root@localhost CA]# touch index.txt
[root@localhost CA]# cp /usr/share/openssl/openssl.cnf

I copied over a few files including openssl.cnf from the /usr/share/ssl and /usr/share/ssl/misc directories:

[root@localhost CA]# cp /usr/share/ssl/openssl.cnf .
[root@localhost CA]# cp /usr/share/ssl/c_* .
[root@localhost CA]# cp /usr/share/ssl/C* .

You can download my openssl.cnf if you wish, for reference. Having done that, it is also useful to setup an environment variable called OPENSSL_CNF so that the various openssl commands look up the configuration from the file in /CA instead of the usual install location. So, I issued the following command:

[root@localhost CA]# export OPENSSL_CONF=/CA/openssl.cnf

Next, the CA needs a certificate for itself. We generate a server certificate (cacert.pem) as well as private key (privkey.pem) using the following command:

[root@localhost CA]# openssl req -x509 -newkey rsa -out cacert.pem -outform PEM
-days 10000 -extensions xpserver_ext
Generating a 1024 bit RSA private key
..............++++++
...++++++
writing new private key to 'privkey.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [PK]:
State or Province Name (full name) [Sind]:
Locality Name (eg, city) [Karachi]:
Organization Name (eg, company) [NED University]:
Organizational Unit Name (eg, section) [CISD]:
Common Name (eg, your name or your server's hostname) [Secure Wireless LAN]:
Email Address [linux@linux.org]:

I then copy the private key file to where it is expected to be found, inside the 'private' folder and save it with a different name, even though this isnt necessary, as this can be changed in openssl.cnf.

[root@localhost CA]# cp privkey.pem ./private/cakey.pem

At this time, it would be useful to look at what we have just produced. You can cat or vi cacert.pem if you wish, but more useful is the following:

[root@localhost CA]# openssl x509 -in cacert.pem -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 0 (0x0)
Signature Algorithm: md5WithRSAEncryption
Issuer: C=PK, ST=Sind, L=Karachi, O=NED University, OU=CISD, CN=Secure Wireless LAN/emailAddress=linux@linux.org
Validity
Not Before: Jul 16 17:12:24 2005 GMT
Not After : Dec 1 17:12:24 2032 GMT
Subject: C=PK, ST=Sind, L=Karachi, O=NED University, OU=CISD, CN=Secure
Wireless LAN/emailAddress=linux@linux.org
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:b5:29:bd:88:15:f0:b0:44:35:91:a1:59:e4:a2:
0b:8c:fa:63:05:0e:8c:e7:0b:3c:0f:96:65:fd:ea:
7e:8c:0f:c3:e5:fc:b0:37:bb:71:9e:74:1f:fe:01:
a6:e5:99:df:fe:8f:47:4c:43:ed:98:ca:79:72:58:
39:53:6c:b0:24:69:31:0d:f2:31:e4:f4:1d:3d:07:
71:c2:e6:49:76:3b:f3:22:4e:b6:17:a3:fe:c1:22:
5d:e6:18:fd:18:30:ab:a1:d7:f3:24:c1:7b:f3:77:
c8:41:eb:bc:48:a4:c4:09:c1:df:8a:fc:e9:ca:00:
ff:f7:77:66:86:bf:55:2a:fb
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Extended Key Usage:
TLS Web Server Authentication
Signature Algorithm: md5WithRSAEncryption
3d:d4:6c:45:98:ee:6d:f9:f1:b8:69:c1:29:8e:fb:e9:1f:d2:
5f:ce:07:52:0e:e7:a1:71:4b:53:12:84:e7:79:50:e7:1b:85:
3b:7a:ba:51:82:a4:46:9d:6e:12:fd:15:c8:f0:80:42:a3:21:
78:f8:f4:65:90:cc:2e:86:c4:b2:2b:a1:bc:6d:89:ce:21:c0:
e8:79:a8:b7:ec:0d:69:52:9f:5a:78:9b:80:f4:61:f4:90:6f:
93:68:f7:9f:0c:79:3f:5e:fe:06:2a:bc:e9:4b:1f:95:3d:59:
87:db:5d:94:4a:a9:78:76:5b:ca:6f:ee:24:4a:85:18:bb:da:
95:cd

Cute, isnt it? Next thing we need to do is to find out the hash for this key and create a file with the name hash.0 from a copy of the certificate. How do you get the hash? There is a utility to do that, that comes with openssl, called c_hash. I invoked it as follows:

[root@localhost CA]# ./c_hash cacert.pem
8dc69078.0 => cacert.pem
Since my openssl.cnf is setup such that a file with the name hash.0 is expected in the newcerts directory, I do the following:

[root@localhost CA]# cp cacert.pem ./newcerts/8dc69078.0

Know that we could also have created a symbloic link back to the certificate file. Next, being the curious kind, I decided to verify the certificate thus:

[root@localhost CA]# openssl verify -CApath ./newcerts/ cacert.pem
cacert.pem: OK

Great! Now let's give the client a certificate. The procedure is quite similar but this time around, we give a different value for "Common Name." First we generate a certificate request.

[root@localhost CA]# openssl req -newkey rsa:1024 -keyout testkey.pem -keyform PEM -out testreq.pem -outform PEM -extensions xpclient_ext
Generating a 1024 bit RSA private key
......++++++
...++++++
writing new private key to 'testkey.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [PK]:
State or Province Name (full name) [Sind]:
Locality Name (eg, city) [Karachi]:
Organization Name (eg, company) [NED University]:
Organizational Unit Name (eg, section) [CISD]:
Common Name (eg, your name or your server's hostname) [Secure Wireless LAN]:LaptopNumber1
Email Address [linux@linux.org]:laptop1@linux.org

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:wireless
NED University []:

Next, we sign it with the CA's key thus:

[root@localhost CA]# openssl ca -in testreq.pem -notext -out testcert.pem
Using configuration from /CA/openssl.cnf
Enter pass phrase for ./private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 3 (0x3)
Validity
Not Before: Jul 16 17:17:44 2005 GMT
Not After : Jul 16 17:17:44 2006 GMT
Subject:
countryName = PK
stateOrProvinceName = Sind
organizationName = NED University
organizationalUnitName = CISD
commonName = LaptopNumber1
emailAddress = laptop1@linux.org
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
NED OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
BC:D7:6F:77:03:FE:94:88:C5:A2:2F:3C:64:43:6B:4E:D9:8F:A3:72
X509v3 Authority Key Identifier:
DirName:/C=PK/ST=Sind/L=Karachi/O=NED University/OU=CISD/CN=Secure Wireless LAN/emailAddress=linux@linux.org
serial:00

Certificate is to be certified until Jul 16 17:17:44 2006 GMT (365 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

Cool! Now we need to put the hash.0 file in the newcerts directory:

[root@localhost CA]# ./c_hash testcert.pem
5bab441e.0 => testcert.pem
[root@localhost CA]# cp testcert.pem ./newcerts/5bab441e.0

Verify:

[root@localhost CA]# openssl verify -CApath ./newcerts/ testcert.pem
testcert.pem: OK

For MS Windows XP, let's convert the PEM file to P12 format.

[root@localhost CA]# openssl pkcs12 -export -in testcert.pem -inkey testkey.pem
-out testcert.p12 -clcerts
Enter pass phrase for testkey.pem:
Enter Export Password:
Verifying - Enter Export Password:

And, let's convert the server certificate to DER format:

[root@localhost CA]# openssl x509 -in cacert.pem -inform PEM -out cacert.der -outform DER -extensions xpclient_ext

There you go! Now transfer cacert.der and testcert.p12 over to the client. I used a floppy disk. First on your Windows XP machine double click on cacert.der and click on install certificate. Click next on the certificate import wizard. Click on the "Place all certificates in the following store:" and click on the Browse button that brings up the select certificate store dialog. Select "Trusted Root Certification Authorities" and click OK. You will be notified that the import was successful.

Next, double click on testcert.p12 and click "next" twice. Type your password in the next dialog and click next. Leave the next dialog's selection as is and click "Next" followed by "Finish." You will be notified that the import was successful.

2 comments:

Whiz Kid said...

Neat stuff! I've done this kind of stuff when I wanted to run a secure apache server with my own cert (for testing only... its prefectly safe but an unimpressive warning pops up on the browser... heh!), never used x.509 though. Were you able to connect to NED ISP through your linux box? pptp didn't work for me. I tried only once though.

Muhammad Saqib Ilyas said...

Yea, I tried doing that. I tried a PPTP software which was available open and free source. I didnt get to browse though. Right now, our wireless clients are all win.