OpenSSL CA and non CA certificate

7

3

I am able to generate a self-signed CA certificate and generate intermediate CA cert.

Now I tried to generate a end-user certificate that should not be able to sign other certificates. So I opened openssl.cnf and change the line in v3_req to basicConstraints=CA:FALSE and generate a .csr using -extensions v3_req and sign it using intermediate CA.

Next I tried to sign another .csr with it and strangely it did the signing. When I tried, the verification was OK.

I'm completely mixed and don`t know what to do. So Any idea what is wrong? These are the commands I used.

$ openssl req -x509 -extensions v3_ca -newkey rsa:2048 \
   -keyout root_ca.key -out root_ca.crt -days 365 \
   -subj /C=US/ST=abc/L=abc/O=test/OU=mine/CN=CA/emailAddress=ca@ca.ca \
   -passout pass:123456

$ openssl req -new -extensions v3_ca -newkey rsa:2048 \
   -keyout s1.key -out s1.csr -days 365 \
   -subj /C=US/ST=abc/L=abc/O=test/OU=mine/CN=s1/emailAddress=s1@ca.ca \
   -passout pass:123456

$ openssl ca -policy policy_anything -outdir ./ -out s1.crt \
   -cert root_ca.crt -infiles s1.csr -CAkey root_ca.key

$ openssl req -new -extensions v3_req -newkey rsa:2048 \
   -keyout client.key -out client.csr -days 365 \
   -subj /C=US/ST=abc/L=abc/O=test/OU=mine/CN=s1/emailAddress=s1@ca.ca \
   -passout pass:123456

$ openssl ca -policy policy_match -outdir ./ -out client.crt -cert s1.crt \
   -infiles client.csr -CAkey s1.key

 $ openssl req -new -extensions v3_req -newkey rsa:2048 \
   -keyout client2.key -out client2.csr -days 365 \
   -subj /C=US/ST=abc/L=abc/O=test/OU=mine/CN=s1/emailAddress=s1@ca.ca \
   -passout pass:123456

 $ openssl ca -policy policy_match -outdir ./ -out client2.crt \
   -cert client.crt -infiles client2.csr -CAkey client.key

 $ cat root_ca.crt s1.crt client.crt > ca.pem

 $ openssl verify -CAfile ca.pem client2.crt

This is the config file:

HOME = .
RANDFILE = $ENV::HOME/.rnd
oid_section = new_oids
[ new_oids ]
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = /root/new
certs = $dir/certs
crl_dir = $dir/crl
database = $dir/index.txt
new_certs_dir = $dir/newcerts
certificate = $dir/root_ca.crt 
serial = $dir/serial 
crlnumber = /root/index.txt
crl = $dir/crl.pem 
private_key = $dir/root_ca.key 
RANDFILE = $dir/private/.rand
x509_extensions = usr_cert
name_opt = ca_default
cert_opt = ca_default
default_days = 365
default_crl_days = 30
default_md = sha1
preserve = no
policy = policy_match
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
default_bits = 1024
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
attributes = req_attributes
x509_extensions = v3_ca
string_mask = nombstr
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = AU
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Some-State
localityName = Locality Name (eg, city)
0.organizationName = Organization Name (eg, company)
0.organizationName_default = Internet Widgits Pty Ltd
organizationalUnitName = Organizational Unit Name (eg, section)
commonName = Common Name (eg, YOUR name)
commonName_max = 64
emailAddress = Email Address
emailAddress_max = 64
[ req_attributes ]
challengePassword = A challenge password
challengePassword_min = 4
challengePassword_max = 20
unstructuredName = An optional company name
[ usr_cert ]
basicConstraints = CA:FALSE
keyUsage = digitalSignature, nonRepudiation,keyEncipherment, dataEncipherment, keyAgreement
nsComment = "OpenSSL Generated Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
[ v3_req ]
basicConstraints = critical,CA:false
keyUsage = nonRepudiation
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
[ v3_ca ]
subjectKeyIdentifier = hash
extendedKeyUsage = critical,serverAuth, clientAuth
basicConstraints = CA:true
keyUsage = cRLSign, keyCertSign, digitalSignature, nonRepudiation,keyEncipherment, dataEncipherment, keyAgreement, keyCertSign, cRLSign
[ crl_ext ]
authorityKeyIdentifier = keyid:always,issuer:always
[ proxy_cert_ext ]
basicConstraints = CA:FALSE
nsComment = "OpenSSL Generated Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
proxyCertInfo = critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo

Hamed JML

Posted 2012-08-16T07:58:37.067

Reputation: 387

As I wrote, I generated a cert which should not be able to sign other certs(by doing ca:false in config file), but it is able to do that. Why? – Hamed JML – 2012-08-21T05:27:05.553

Weird. Your openssl ca ... -CAkey ... should give an error, as -CAkey is only valid on openssl x509 (on ca, -keyfile should be used). Can you check alias openssl and which openssl, as well as $SSLEAY_CONF and OPENSSL_CONF? This could be the cause, as your [req] section contains v3_ca, and therefore all your requests would output a self-signed certificate instead of a certificate request. – tricasse – 2012-08-23T11:37:27.923

I think I wrote it wrong. the option is -keyfile and when I use a wrong ca public key file, the verification fails. – Hamed JML – 2012-08-24T09:21:42.137

Where you able to try the steps I suggested in my comment below? They should generate a valid root ca + intermediate ca + final user cert on any OpenSSL setup; they'll just use default values from the default/sample OpenSSL configuration. You might then add your customisations like rsa:2048, and adapt the config file to your liking. – tricasse – 2012-08-24T22:48:56.660

And if it's not working with my proposal, then we can investigate if something is wrong with your setup... see the checks I suggested. – tricasse – 2012-08-24T22:50:11.290

Answers

6

Did you try with basicConstraints=critical,CA:false?

PS: The 'ca' utility doesn't currently check the validity of the CA certificate it is signing with. So it will happily sign with an invalid CA but the verification routines will reject it.

The following, while a bit verbose, should work; can you try it on your setup and report any issues?

#!/bin/sh
#SSLEAY_CONFIG="-config yourfile.cnf"
ROOTCA_SUBJ="-subj /C=US/ST=abc/L=abc/O=test/OU=mine/CN=RootCA/emailAddress=rootca@example.org"
CA_SUBJ="-subj /C=US/ST=abc/L=abc/O=test/OU=mine/CN=CA/emailAddress=ca@example.org"
CERT_SUBJ="-subj /C=US/ST=abc/L=abc/O=test/OU=mine/CN=cert/emailAddress=cert@example.org"
ROOTCA_PASS="pass:test"
CA_PASS="pass:test"
CERT_PASS="pass:test"
DIR="demoCA"
mkdir "$DIR" "$DIR"/certs "$DIR"/crl "$DIR"/newcerts "$DIR"/private
touch "$DIR"/index.txt
echo 01 > "$DIR"/crlnumber

# create Root CA
mkdir rootCA rootCA/certs rootCA/crl rootCA/newcerts rootCA/private
openssl req $SSLEAY_CONFIG -new -keyout rootCA/private/rootCAkey.pem -out rootCA/rootCAreq.pem $ROOTCA_SUBJ -passout "$ROOTCA_PASS"
openssl ca $SSLEAY_CONFIG -create_serial -out rootCA/rootCAcert.pem -days 1095 -batch -keyfile rootCA/private/rootCAkey.pem -passin "$ROOTCA_PASS" -selfsign -extensions v3_ca -infiles rootCA/rootCAreq.pem

# create Intermediate CA
mkdir CA CA/certs CA/crl CA/newcerts CA/private
openssl req $SSLEAY_CONFIG -new -keyout CA/private/CAkey.pem -out CA/CAreq.pem -days 365 $CA_SUBJ -passout "$CA_PASS"
openssl ca $SSLEAY_CONFIG -cert rootCA/rootCAcert.pem -keyfile rootCA/private/rootCAkey.pem -passin "$ROOTCA_PASS" -policy policy_anything -out CA/CAcert.pem -extensions v3_ca -infiles CA/CAreq.pem

# create Final Cert
mkdir cert cert/private
openssl req $SSLEAY_CONFIG -new -keyout cert/private/certkey.pem -out cert/certreq.pem -days 365 $CERT_SUBJ -passout "$CERT_PASS"
openssl ca $SSLEAY_CONFIG -cert CA/CAcert.pem -keyfile CA/private/CAkey.pem -passin "$CA_PASS" -policy policy_anything -out cert/cert.pem -infiles cert/certreq.pem
cat rootCA/rootCAcert.pem CA/CAcert.pem > myCA.pem
openssl verify -CAfile myCA.pem cert/cert.pem

When you run openssl verify, -CAfile implies you trust this certificate. So -CAfile should only contain the root-CA, and optionally the intermediate-CA; else it will always return OK. Other certificates should be added through the -untrusted option.

Therefore, if you give it a cert2.pem certificate, signed by the final cert.pem certificate, you'll get:

$ cat CA/CAcert.pem cert/cert.pem > notrust.pem
$ openssl verify -CAfile myCA.pem -untrusted notrust.pem cert2/cert2.pem
    cert2/cert2.pem: C = US, ST = abc, L = abc, O = test, OU = mine, CN = cert, emailAddress = cert@example.org
    error 24 at 1 depth lookup:invalid CA certificate

tricasse

Posted 2012-08-16T07:58:37.067

Reputation: 513

Yes, I tried it and my question is why this does not work!? – Hamed JML – 2012-08-22T04:24:02.577

Can you provide us with a copy of your .cnf file? – tricasse – 2012-08-22T18:06:40.927

As well as the steps you did to get there (or a link to a howto you might have followed) – tricasse – 2012-08-22T18:16:56.627

Added. But it get very very long. Perhaps most of it was really not needed, but maybe it is. – Hamed JML – 2012-08-23T04:24:10.463

I used the final cert to sign another certificate, and when I tried to verify it using openssl, it showed verification OK. – Hamed JML – 2012-08-25T05:22:59.073

Ok, got it. Answer above (no space here). – tricasse – 2012-08-27T04:17:06.503

2

As stated before, the CA utility will happily sign a request with any certificate, even if it is not a CA certificate. Apparently, some older browsers (at a minimum, Firefox versions prior to 33) would even accept such chains.

To find out if your certificate has the isCA bit set, run:

openssl x509 -text -noout -in your_cert_file.crt

In the output, look for the following:

X509v3 Basic Constraints: 
    CA:TRUE

This is a CA certificate. A non-CA cert would have CA:FALSE (or not have the extension at all).

Caveat: you need to include these extensions in your request AND make sure the CA does not override them when signing the request.

user149408

Posted 2012-08-16T07:58:37.067

Reputation: 778