> Markdown version of https://docs.laavat.io/usage/productguide/pki/ from the LAAVAT PKI and Signing Platform documentation. All pages: https://docs.laavat.io/llms.txt

# PKI Configuration

The Public Key Infrastructure (PKI) part consists of creating Root Certificate Authorities for (Advanced) High Assurance Boot use case ((A)HAB CA) and the associated End-Entity certificates issued under those roots.

PKI profiles are provided as templates. Profiles are modified per use case. Generally the "Validity period", "Distinguished Name" are modified.

For (A)HAB CAs the naming must contain SRK{0...3} so that the correct SRK can be selected. By default, the SRK0 will be the first CA.
Also the End-Entity Common names must contain IMG{0...3}, CSF{0...3} or SGK{0...3} so that the correct End-Entity is used. The Common name must be empty since it is populated from the product information.

## Supported Algorithms

Supported Key Algorithms:

* RSA
* ECDSA
* ML-DSA (FIPS 204, post-quantum)
* AES

Supported Key Sizes:

* 2048, 3072 & 4096 bits for RSA
* ECDSAP224, ECDSAP256, ECDSAP384, ECDSAP521 for ECDSA
* MLDSA44, MLDSA65, MLDSA87 for ML-DSA
* 128 & 256 bits for AES

## CAInfo fields in the product 

Field                          | Usage
-------------------------------|--------------------------------------------------
crlIssueInterval | A fixed interval when CRL will be issued. Duration string is a possibly signed sequence of decimal numbers, each with optional fraction and a unit suffix, such as "300ms", "1.5h" or "2h45m". Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
crlExpiry | The validity period for generated CRL. Duration string is a possibly signed sequence of decimal numbers, each with optional fraction and a unit suffix, such as "300ms", "1.5h" or "2h45m". Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
crlDistributionPoints | Array CRL distribution points for a CA. These will override the distribution points in the certificate profile to be issued if present.
policyIdentifiers | Array of Certificate policy identifiers. These will override the policy identifiers in the certificate profile to be issued if present.

Other fields are described in the [REST API Documentation.](https://docs.laavat.io/api/swagger/)

## Certificate Profiles

Certificate profiles for different use cases can be created by providing a YAML template to the System. This is done as part of the configuration. Profiles can be specific for a product or shared between multiple products.
The templates define the KeyUsage, validities etc. Some of the values can be overridden by the CSR.

## Examples of profiles

See [examples by use case](https://docs.laavat.io/usage/productguide/pki-examples/)

More examples of profile YAML files are available in the reference client package. Contact [support@laavat.io](mailto:support@laavat.io) for the package.

## Creating a profile to the Solution

Adding new profiles are done in the following way:

1. Identify the use case. If there is an existing profile, use that in the product creation.
2. If the new profile is needed modify the values in the profile.
3. Upload the profile to the Solution. The person doing the upload must be in the groups listed for CA Write access.
4. No Approval is needed.
5. Make note of the returned profile ID.

## Profile structure

### Name

Name of the profile so it can be identified more easily

```yaml
Name: Initial Device Certificate EndEntity Profile
```

### DN

DN specifies the fields which are overwritten from the CSR. In example below the Organization and County are written to the issued certificate.

```yaml
DN:
  #Organization: Test Comp
  Organization: Laavat
  #OrganizationalUnit: R&D
  #Country: FI
  Country: FI
  #Province:
  #- Something
  # Locality:
  # StreetAddress:
  # PostalCode:
  # SerialNumber
  # CommonName: 
```

### Profile Type

If creating a ROOT then profile 3 is selected

```yaml
# EndEntity is 1, Sub CA profile 2 , Root profile 3
ProfileType: 3
```

### Signature Algorithms

Must match the selected keytype

```yaml
# SignatureAlgorithms
#  SHA1WithRSA = 3
#  SHA256WithRSA = 4
#  SHA384WithRSA = 5
#  SHA512WithRSA = 6
#  DSAWithSHA1 = 7 // Unsupported.
#  DSAWithSHA256 = 8 // Unsupported.
#  ECDSAWithSHA1 = 9
#  ECDSAWithSHA256 = 10
#  ECDSAWithSHA384 = 11
#  ECDSAWithSHA512 = 12
#  SHA256WithRSAPSS = 13
#  SHA384WithRSAPSS = 14
#  SHA512WithRSAPSS = 15
#  MLDSA44 = 17
#  MLDSA65 = 18
#  MLDSA87 = 19
SignatureAlgorithm: 10
```

The signature algorithm is that of the **issuer's** key. A certificate issued by a CA with an `MLDSA65` key uses
`SignatureAlgorithm: 18`, whatever the key type of the certificate itself; a mismatch between the signature algorithm and the
issuing key is rejected. ML-DSA has no separate hash, so there is one value per parameter set.

### Key Algorithm

Must match the key algorithm in the product. E.g. if (A)HAB tree is using RSA keys then the profile must set RSAAlgorithm = 1

```yaml
# KeyAlgorithms
#   RSAAlgorithm = 1
#   ECDSAAlgorithm = 2
#   MLDSAAlgorithm = 3
KeyAlgorithm: 2
```

For example, a root CA with an `MLDSA65` key uses `KeyAlgorithm: 3` and `SignatureAlgorithm: 18`. An EC device certificate
issued by that CA uses `KeyAlgorithm: 2` (its own key) and `SignatureAlgorithm: 18` (the issuer's key).

### Validity Period

Validity of the certificate in duration (max 290 years) or with absolute date in RFC3339 e.g. 9999-12-31T23:59:59Z. Example in absolute date "9999-12-31T23:59:59Z".
Example in duration "1h10m10s". Only h, m and/or s are accepted.

```yaml
ValidityPeriod: 1577846300
```

### Basic Constraints

Basic constraints for the certificate

```yaml
BasicConstraints:
  BasicConstraintsValid: true
  IsCA: false
  ```

### Identifiers

Add Authority Key Indentifier or Subject Key identifier

```yaml
AddSKI: true
AddAKI: true
```

### Key Usages

Selects the needed Key Usages. The profile of a CA (root or sub CA) must list 32 (CertSign) and 64 (CRLSign): the platform signs the CA's CRL with the CA certificate, and product creation refuses a CA profile without 64. HAB SRK profiles are the exception, as no CRL is issued for an SRK.

```yaml
# KeyUsages
#  KeyUsageDigitalSignature = 1
#  KeyUsageContentCommitment = 2
#  KeyUsageKeyEncipherment = 4
#  KeyUsageDataEncipherment = 8
#  KeyUsageKeyAgreement = 16
#  KeyUsageCertSign = 32 
#  KeyUsageCRLSign = 64
#  KeyUsageEncipherOnly = 128
#  KeyUsageDecipherOnly = 256
KeyUsage:
  - 1
  - 16
```

### Extended Key Usage

Select the extended key usages

```yaml
ExtendedKeyUsage:
  # ExtendedKeyUsages
  #  ExtKeyUsageAny = 0
  #  ExtKeyUsageServerAuth = 1
  #  ExtKeyUsageClientAuth = 2
  #  ExtKeyUsageCodeSigning = 3
  #  ExtKeyUsageEmailProtection = 4
  #  ExtKeyUsageIPSECEndSystem = 5
  #  ExtKeyUsageIPSECTunnel = 6
  #  ExtKeyUsageIPSECUser = 7
  #  ExtKeyUsageTimeStamping = 8
  #  ExtKeyUsageOCSPSigning = 9
  #  ExtKeyUsageMicrosoftServerGatedCrypto = 10
  #  ExtKeyUsageNetscapeServerGatedCrypto = 11
  #  ExtKeyUsageMicrosoftCommercialCodeSigning = 12
  #  ExtKeyUsageMicrosoftKernelCodeSigning = 13
  - 1
  - 2
```

### Additional fields

```yaml
ExtraExtensions: true
SANUsage: true
# CRLDistributionPoints. List of URI strings.
CRLDistributionPoints:
  - http://crl.company.com/e37f045c.crl

# PolicyIdentifiers. List of ASN1 policy OIDS
PolicyIdentifiers:
  - 1.10.123.432.4.5
  - 2.10.123.432.4.65
```

### Enforcements

#### Version 1 profile

Values of options              | Behavior
-------------------------------|--------------------------------------------------
EnforceUniqueDN: false | New certificate is issued every time.
EnforceUniqueDN: true  | If certificate has been issued with the same DN from the CA then that certificate is returned. If PublicKey has been used and different DN is requested in the CSR then an error is returned.

#### Version 2 profile

Values of options              | Behavior
-------------------------------|--------------------------------------------------
EnforceUniqueDN: false AND EnforceUniquePublicKey: false | New certificate is issued every time.
EnforceUniqueDN: true AND EnforceUniquePublicKey: false  | If certificate has been issued with the same DN from the CA then that certificate is returned. Otherwise a new certificate is returned.
EnforceUniqueDN: false AND EnforceUniquePublicKey: true  | If same public key has been used before from that CA an error will be returned. Otherwise a new certificate is issued.
EnforceUniqueDN: true AND EnforceUniquePublicKey: true   | If certificate has been issued with the same DN from the CA with the same public key then that found certificate is returned. If public key and DN are new then a new certificate is issued. Otherwise an error is returned.

### CDPs and PolicyIdentifiers

It is possible to have CA specific CDPs and PolicyIdentifiers that override the ones defined in the profiles.

Field                         | Usage
-------------------------------|--------------------------------------------------
crlDistributionPoints | Array CRL distribution points for a CA. These will override the distribution points in the certificate profile to be issued if present.
policyIdentifiers     | Array of Certificate policy identifiers. These will override the policy identifiers in the certificate profile to be issued if present.

## Example usage with reference client package: add profiles

> **Note: Token handling**
> These commands use `-n test.ini` — a config file created with `config-init` that references a `token_file` and the API URL, so no token appears on the command line. See [Reference Client › Usage](https://docs.laavat.io/democlient/usage/) for how to create the config and for the secure token-input forms (`-t @file`, `-t @-`).

These profiles will be usable by CA trees defined in products. Profile types are ROOT, SUB and END, for Root CA, Intermediate/Sub-CA and End-Entity/Leaf-certificate respectively.

Add a root profile:

```bash
(venv) $ signing-tool -n test.ini profile add \
    -N TESTING -T ROOT -F nxp-imx6-habv4-rootca-rsa-4096-SHA256-profile.yaml 
{
    "id": "76de3349-3707-4744-b7d0-93ae7ea349c0",
    "profile_name": "TESTING",
    "profile_type": 3,
    "profile_yaml": "<Redacted for readability>"
}
Profile added. Profile ID: 76de3349-3707-4744-b7d0-93ae7ea349c0
```

Add a Sub-CA profile:

```bash
(venv) $ signing-tool -n test.ini profile add \
    -N TESTINGSUB -T SUB -F nxp-imx6-habv4-subca-rsa-4096-SHA256-profile.yaml 
{
    "id": "f8118cc1-9afd-490f-8783-b2104bf3cb87",
    "profile_name": "TESTINGSUB",
    "profile_type": 2,
    "profile_yaml": "<Redacted for readability>"
}
Profile added. Profile ID: f8118cc1-9afd-490f-8783-b2104bf3cb87
```

Add an End-Entity profile:

```bash
(venv) $ signing-tool -n test.ini profile add \
    -N TESTINGEND -T END -F nxp-imx6-habv4-endentity-rsa-4096-SHA256-profile.yaml 
{
    "id": "60b3ff9e-27f9-403c-b125-e018080a6366",
    "profile_name": "TESTINGEND",
    "profile_type": 1,
    "profile_yaml": "<Redacted for readability>"
}
Profile added. Profile ID: 60b3ff9e-27f9-403c-b125-e018080a6366
```

## Example usage with reference client package: modify profiles

After creation, profiles can be modified by updating one, several, or all fields within the data structure as required. Be aware that since profiles may be utilized across multiple products, altering the profile data could potentially cause unintended side effects in some of those products.

Modifying the root profile using reference client. ./prof.yaml has the new profile:

```bash
(venv) $ signing-tool -n test.ini profile update \
 -F ./prof.yaml -I 76de3349-3707-4744-b7d0-93ae7ea349c0
Profile updated
```
