Certificate Setup

Certificate-based authentication requires proper PKI infrastructure. This guide covers the certificate requirements, installation, and management for Linux EAP-TLS clients.

Certificate Types Required

EAP-TLS requires three certificate components on the client:

Certificate Purpose Location

CA Certificate

Trust anchor for validating RADIUS server

/etc/ssl/certs/ca-chain.pem

Client Certificate

Proves client identity to RADIUS server

/etc/ssl/certs/-eaptls.pem

Private Key

Signs the TLS handshake

/etc/ssl/private/-eaptls.key

Certificate Requirements

Client Certificate

The client certificate must meet these requirements:

Attribute Requirement

Subject CN

Hostname or machine identifier

Subject Alternative Name (SAN)

DNS name, optionally UPN

Extended Key Usage (EKU)

Client Authentication (1.3.6.1.5.5.7.3.2)

Key Usage

Digital Signature

Key Size

RSA 2048+ or ECDSA P-256+

Validity

1 year typical

CA Certificate Chain

The CA chain file should include:

  • Root CA certificate

  • Intermediate CA certificate(s)

The chain validates the RADIUS server certificate during the TLS handshake.

Obtaining Certificates

From Internal PKI

If your organization runs an internal PKI (Active Directory Certificate Services, HashiCorp Vault PKI, etc.):

# Example: Request from Vault PKI
vault write pki_int/issue/eap-tls-client \
    common_name="<hostname>.<domain>" \
    alt_names="<hostname>.<domain>" \
    ttl="8760h" \
    -format=json > /tmp/cert.json

# Extract certificate
jq -r '.data.certificate' /tmp/cert.json > /etc/ssl/certs/<hostname>-eaptls.pem

# Extract private key
jq -r '.data.private_key' /tmp/cert.json > /etc/ssl/private/<hostname>-eaptls.key

# Extract CA chain
jq -r '.data.ca_chain[]' /tmp/cert.json > /etc/ssl/certs/ca-chain.pem

# Clean up
rm /tmp/cert.json

From SCEP/EST

For automated enrollment via SCEP or EST protocols:

# Generate CSR
openssl req -new -nodes \
    -newkey rsa:2048 \
    -keyout /etc/ssl/private/<hostname>-eaptls.key \
    -out /tmp/<hostname>.csr \
    -subj "/CN=<hostname>.<domain>"

# Submit CSR to SCEP server (example using sscep)
sscep enroll \
    -u https://scep.example.com/certsrv/mscep/mscep.dll \
    -c /tmp/ca.pem \
    -k /etc/ssl/private/<hostname>-eaptls.key \
    -r /tmp/<hostname>.csr \
    -l /etc/ssl/certs/<hostname>-eaptls.pem

Manual Certificate Request

For manual enrollment:

# Generate private key
openssl genrsa -out /etc/ssl/private/<hostname>-eaptls.key 2048

# Generate CSR
openssl req -new \
    -key /etc/ssl/private/<hostname>-eaptls.key \
    -out /tmp/<hostname>.csr \
    -subj "/CN=<hostname>.<domain>"

# View CSR for submission
cat /tmp/<hostname>.csr

Submit the CSR to your CA administrator and receive the signed certificate.

Installing Certificates

Directory Structure

# Create directories if needed
sudo mkdir -p /etc/ssl/certs
sudo mkdir -p /etc/ssl/private

Copy Certificates

# Copy CA chain
sudo cp ca-chain.pem /etc/ssl/certs/ca-chain.pem

# Copy client certificate
sudo cp <hostname>-eaptls.pem /etc/ssl/certs/<hostname>-eaptls.pem

# Copy private key
sudo cp <hostname>-eaptls.key /etc/ssl/private/<hostname>-eaptls.key

Set Permissions

Critical security step — private keys must be protected:

# CA chain - readable
sudo chmod 644 /etc/ssl/certs/ca-chain.pem
sudo chown root:root /etc/ssl/certs/ca-chain.pem

# Client certificate - readable
sudo chmod 644 /etc/ssl/certs/<hostname>-eaptls.pem
sudo chown root:root /etc/ssl/certs/<hostname>-eaptls.pem

# Private key - root only
sudo chmod 600 /etc/ssl/private/<hostname>-eaptls.key
sudo chown root:root /etc/ssl/private/<hostname>-eaptls.key

Verify Permissions

ls -la /etc/ssl/private/<hostname>-eaptls.key
# Expected: -rw------- 1 root root

ls -la /etc/ssl/certs/<hostname>-eaptls.pem
# Expected: -rw-r--r-- 1 root root

Verification

Verify Certificate Chain

# Verify client cert against CA chain
openssl verify -CAfile /etc/ssl/certs/ca-chain.pem \
    /etc/ssl/certs/<hostname>-eaptls.pem

# Expected: /etc/ssl/certs/hostname-eaptls.pem: OK

Verify Key Matches Certificate

# Get certificate modulus
openssl x509 -in /etc/ssl/certs/<hostname>-eaptls.pem -noout -modulus | md5sum

# Get key modulus
openssl rsa -in /etc/ssl/private/<hostname>-eaptls.key -noout -modulus | md5sum

# Both hashes must match

View Certificate Details

# View certificate
openssl x509 -in /etc/ssl/certs/<hostname>-eaptls.pem -noout -text

# View just the important fields
openssl x509 -in /etc/ssl/certs/<hostname>-eaptls.pem -noout \
    -subject -issuer -dates -ext extendedKeyUsage,subjectAltName

Check Expiration

# View certificate dates
openssl x509 -in /etc/ssl/certs/<hostname>-eaptls.pem -noout -dates

# Check if expired
openssl x509 -in /etc/ssl/certs/<hostname>-eaptls.pem -noout -checkend 0
# Returns 0 if valid, 1 if expired

Certificate Renewal

Monitor Expiration

Create a systemd timer to check certificate expiration:

# /etc/systemd/system/cert-check.service
[Unit]
Description=Check EAP-TLS certificate expiration

[Service]
Type=oneshot
ExecStart=/usr/local/bin/cert-check.sh
# /etc/systemd/system/cert-check.timer
[Unit]
Description=Weekly certificate expiration check

[Timer]
OnCalendar=weekly
Persistent=true

[Install]
WantedBy=timers.target

Check Script

#!/bin/bash
# /usr/local/bin/cert-check.sh

CERT="/etc/ssl/certs/<hostname>-eaptls.pem"
DAYS_WARNING=30

# Check if cert expires within warning period
if ! openssl x509 -in "$CERT" -noout -checkend $((DAYS_WARNING * 86400)); then
    echo "WARNING: Certificate expires within $DAYS_WARNING days"
    # Add notification logic (email, logging, etc.)
fi

Renewal Process

  1. Generate new CSR or request new certificate from PKI

  2. Install new certificate (same paths)

  3. Restart wpa_supplicant:

sudo systemctl restart wpa_supplicant-wired@<interface>

Troubleshooting

Certificate Chain Incomplete

Symptom: RADIUS rejects with "certificate verify failed"

Solution: Ensure ca-chain.pem contains full chain:

# View chain
openssl crl2pkcs7 -nocrl -certfile /etc/ssl/certs/ca-chain.pem | \
    openssl pkcs7 -print_certs -noout

# Should show: Root CA, then Intermediate CA(s)

Wrong EKU

Symptom: Certificate valid but authentication rejected

Check:

openssl x509 -in /etc/ssl/certs/<hostname>-eaptls.pem -noout -text | grep -A2 "Extended Key"
# Must show: TLS Web Client Authentication

Permission Denied

Symptom: wpa_supplicant fails with "Could not read private key"

Fix:

sudo chmod 600 /etc/ssl/private/<hostname>-eaptls.key
sudo chown root:root /etc/ssl/private/<hostname>-eaptls.key