# Generate keys and certificates

## Generate local (insecure) root key and certificate

The version 3 (v3 and v3\_attest) extensions define the certificate format and establish the Certificate Authority (CA). This process allows you to create a local CA with specific attributes and constraints set by the v3 extensions, allowing you to issue certificates for testing and development purposes.

Follow these steps to generate a local root key and certificate.

1. Create an `opensslroot.cfg` using the following sample OpenSSL configuration file:

    OpenSSL is an open-source toolkit for secure sockets layer (SSL) and transport layer security (TLS) protocols, offering cryptographic functions and a command-line tool.

    The following sample OpenSSL configuration file is used for generating certificate requests and managing a Certificate Authority (CA).

> 
> 
> #
>         #  Copyright (c) 2013 Qualcomm Technologies, Inc.
>         #  All Rights Reserved.
>         #  Confidential and Proprietary - Qualcomm Technologies, Inc.
>         #
>         # OpenSSL example configuration file.
>         # This is mostly being used for generation of certificate requests.
>         #
>         
>         # This definition stops the following lines choking if HOME isn't
>         # defined.
>         HOME            = .
>         RANDFILE        = $ENV::HOME/.rnd
>         
>         # Extra OBJECT IDENTIFIER info:
>         #oid_file       = $ENV::HOME/.oid
>         oid_section     = new_oids
>         
>         # To use this configuration file with the "-extfile" option of the
>         # "openssl x509" utility, name here the section containing the
>         # X.509v3 extensions to use:
>         # extensions        =
>         # (Alternatively, use a configuration file that has only
>         # X.509v3 extensions in its main [= default] section.)
>         
>         [ new_oids ]
>         
>         # We can add new OIDs in here for use by 'ca' and 'req'.
>         # Add a simple OID like this:
>         # testoid1=1.2.3.4
>         # Or use config file substitution like this:
>         # testoid2=${testoid1}.5.6
>         
>         ####################################################################
>         [ ca ]
>         default_ca  = CA_default        # The default ca section
>         
>         ####################################################################
>         [ CA_default ]
>         
>         dir     = ./demoCA      # Where everything is kept
>         certs       = $dir/certs        # Where the issued certs are kept
>         crl_dir     = $dir/crl      # Where the issued crl are kept
>         database    = $dir/index.txt    # database index file.
>         #unique_subject = no            # Set to 'no' to allow creation of
>         # several certificates with same subject.
>         new_certs_dir   = $dir/newcerts     # default place for new certs.
>         
>         certificate = $dir/cacert.pem   # The CA certificate
>         serial      = $dir/serial       # The current serial number
>         crlnumber   = $dir/crlnumber    # the current crl number
>         # must be commented out to leave a V1 CRL
>         crl     = $dir/crl.pem      # The current CRL
>         private_key = $dir/private/cakey.pem# The private key
>         RANDFILE    = $dir/private/.rand    # private random number file
>         
>         x509_extensions = usr_cert      # The extensions to add to the cert
>         
>         # Comment out the following two lines for the "traditional"
>         # (and highly broken) format.
>         name_opt    = ca_default        # Subject Name options
>         cert_opt    = ca_default        # Certificate field options
>         
>         # Extension copying option: use with caution.
>         # copy_extensions = copy
>         
>         # Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
>         # so this is commented out by default to leave a V1 CRL.
>         # crlnumber must also be commented out to leave a V1 CRL.
>         # crl_extensions    = crl_ext
>         
>         default_days    = 365           # how long to certify for
>         default_crl_days= 30            # how long before next CRL
>         default_md  = sha1          # which md to use.
>         preserve    = no            # keep passed DN ordering
>         
>         # A few different ways of specifying how similar the request should look
>         # For type CA, the listed attributes must be the same, and the optional
>         # and supplied fields are just that :-)
>         policy      = policy_match
>         
>         # For the CA policy
>         [ policy_match ]
>         countryName     = match
>         stateOrProvinceName = match
>         organizationName    = match
>         organizationalUnitName  = optional
>         commonName      = supplied
>         emailAddress        = optional
>         
>         # For the 'anything' policy
>         # At this point in time, you must list all acceptable 'object'
>         # types.
>         [ 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 # The extensions to add to the self signed cert
>         
>         # Passwords for private keys if not present they will be prompted for
>         # input_password = secret
>         # output_password = secret
>         
>         # This sets a mask for permitted string types. There are several options.
>         # default: PrintableString, T61String, BMPString.
>         # pkix   : PrintableString, BMPString.
>         # utf8only: only UTF8Strings.
>         # nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
>         # MASK:XXXX a literal mask value.
>         # WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
>         # so use this option with caution!
>         string_mask = nombstr
>         
>         req_extensions = v3_req # The extensions to add to a certificate request
>         
>         [ 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
>         
>         # we can do this but it is not needed normally :-)
>         #1.organizationName     = Second Organization Name (eg, company)
>         #1.organizationName_default = World Wide Web Pty Ltd
>         
>         organizationalUnitName      = Organizational Unit Name (eg, section)
>         #organizationalUnitName_default =
>         
>         commonName          = Common Name (eg, YOUR name)
>         commonName_max          = 64
>         
>         emailAddress            = Email Address
>         emailAddress_max        = 64
>         
>         # SET-ex3           = SET extension number 3
>         
>         [ req_attributes ]
>         challengePassword       = A challenge password
>         challengePassword_min       = 4
>         challengePassword_max       = 20
>         
>         unstructuredName        = An optional company name
>         
>         [ usr_cert ]
>         
>         # These extensions are added when 'ca' signs a request.
>         
>         # This goes against PKIX guidelines but some CAs do it and some software
>         # requires this to avoid interpreting an end user certificate as a CA.
>         
>         basicConstraints=CA:FALSE
>         keyUsage = nonRepudiation, digitalSignature, keyEncipherment
>         
>         # Here are some examples of the usage of nsCertType. If it is omitted
>         # the certificate can be used for anything *except* object signing.
>         
>         # This is OK for an SSL server.
>         # nsCertType            = server
>         
>         # For an object signing certificate this would be used.
>         # nsCertType = objsign
>         
>         # For normal client use this is typical
>         # nsCertType = client, email
>         
>         # and for everything including object signing:
>         # nsCertType = client, email, objsign
>         
>         # This is typical in keyUsage for a client certificate.
>         # keyUsage = nonRepudiation, digitalSignature, keyEncipherment
>         
>         # This will be displayed in Netscape's comment listbox.
>         nsComment           = "OpenSSL Generated Certificate"
>         
>         # PKIX recommendations harmless if included in all certificates.
>         subjectKeyIdentifier=hash
>         authorityKeyIdentifier=keyid,issuer
>         
>         # This stuff is for subjectAltName and issuerAltname.
>         # Import the email address.
>         # subjectAltName=email:copy
>         # An alternative to produce certificates that aren't
>         # deprecated according to PKIX.
>         # subjectAltName=email:move
>         
>         # Copy subject details
>         # issuerAltName=issuer:copy
>         
>         #nsCaRevocationUrl      = http://www.domain.dom/ca-crl.pem
>         #nsBaseUrl
>         #nsRevocationUrl
>         #nsRenewalUrl
>         #nsCaPolicyUrl
>         #nsSslServerName
>         
>         [ v3_req ]
>         
>         # Extensions to add to a certificate request
>         
>         subjectKeyIdentifier=hash
>         
>         #authorityKeyIdentifier=keyid:always,issuer:always
>         
>         basicConstraints = CA:FALSE
>         keyUsage = nonRepudiation, digitalSignature, keyEncipherment
>         
>         [ v3_ca ]
>         
>         
>         # Extensions for a typical CA
>         
>         
>         # PKIX recommendation.
>         
>         subjectKeyIdentifier=hash
>         
>         #authorityKeyIdentifier=keyid:always,issuer:always
>         
>         # This is what PKIX recommends but some broken software chokes on critical
>         # extensions.
>         #basicConstraints = critical,CA:true
>         # So we do this instead.
>         basicConstraints = CA:true
>         
>         # Key usage: this is typical for a CA certificate. However since it will
>         # prevent it from being used as a test self-signed certificate, it is best to be
>         # left out as a default.
>         keyUsage = cRLSign, keyCertSign
>         
>         # Some might want this also
>         # nsCertType = sslCA, emailCA
>         
>         # Include email address in subject alt name: another PKIX recommendation
>         # subjectAltName=email:copy
>         # Copy issuer details
>         # issuerAltName=issuer:copy
>         
>         # DER hex encoding of an extension: beware experts only!
>         # obj=DER:02:03
>         # Where 'obj' is a standard or added object
>         # You can even override a supported extension:
>         # basicConstraints= critical, DER:30:03:01:01:FF
>         
>         [ crl_ext ]
>         
>         # CRL extensions.
>         # Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
>         
>         # issuerAltName=issuer:copy
>         authorityKeyIdentifier=keyid:always,issuer:always
>         
>         [ proxy_cert_ext ]
>         # These extensions should be added when creating a proxy certificate
>         
>         # This goes against PKIX guidelines but some CAs do it and some software
>         # requires this to avoid interpreting an end user certificate as a CA.
>         
>         basicConstraints=CA:FALSE
>         
>         # Here are some examples of the usage of nsCertType. If it is omitted
>         # the certificate can be used for anything *except* object signing.
>         
>         # This is OK for an SSL server.
>         # nsCertType            = server
>         
>         # For an object signing certificate this would be used.
>         # nsCertType = objsign
>         
>         # For normal client use this is typical
>         # nsCertType = client, email
>         
>         # and for everything including object signing:
>         # nsCertType = client, email, objsign
>         
>         # This is typical in keyUsage for a client certificate.
>         # keyUsage = nonRepudiation, digitalSignature, keyEncipherment
>         
>         # This will be displayed in Netscape's comment listbox.
>         nsComment           = "OpenSSL Generated Certificate"
>         
>         # PKIX recommendations harmless if included in all certificates.
>         subjectKeyIdentifier=hash
>         authorityKeyIdentifier=keyid,issuer:always
>         
>         # This stuff is for subjectAltName and issuerAltname.
>         # Import the email address.
>         # subjectAltName=email:copy
>         # An alternative to produce certificates that aren't
>         # deprecated according to PKIX.
>         # subjectAltName=email:move
>         
>         # Copy subject details
>         # issuerAltName=issuer:copy
>         
>         #nsCaRevocationUrl      = http://www.domain.dom/ca-crl.pem
>         #nsBaseUrl
>         #nsRevocationUrl
>         #nsRenewalUrl
>         #nsCaPolicyUrl
>         #nsSslServerName
>         
>         # This really needs to be in place for it to be a proxy certificate.
>         proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
>         Copy to clipboard
2. To create the `v3.ext` and `v3_attest.ext` extensions, use the following:

    - `v3.ext`: This extension can be found at
 [/docs/manmaster/man5/x509v3_config.html (OpenSSL.org)](https://www.openssl.org/docs/manmaster/man5/x509v3_config.html),
and include the following settings:

authorityKeyIdentifier=keyid,issuer
            subjectKeyIdentifier=hash
            basicConstraints=CA:true,pathlen:0
            keyUsage=keyCertSign
            Copy to clipboard
    - `v3_attest.ext`: This extension can be found
at [/docs/manmaster/man5/x509v3_config.html (OpenSSL.org)](https://www.openssl.org/docs/manmaster/man5/x509v3_config.html),
and include the following settings:

authorityKeyIdentifier=keyid,issuer
            basicConstraints=CA:FALSE,pathlen:0
            keyUsage=digitalSignature
            extendedKeyUsage=codeSigning
            Copy to clipboard
3. Prepare the environment, create a directory named OEM-KEYS to generate all certificates and keys at one location.

    - For Linux, use the following commands:

cd /path/to/sectools/$ mkdir ./OEM-KEYS &&
            cp /download/opensslroot.cfg ./OEM-KEYS &&
            cp /download/v3.ext ./OEM-KEYS &&
            cp /download/v3_attest.ext ./OEM-KEYS
            Copy to clipboard
    - For Windows, copy `opensslroot.cfg`, `v3.ext`, and `v3_attest.ext` to the OEM-KEYS directory.

The table lists the supported cryptographic algorithms.

Table : Cryptographic algorithms

| IQ-615 | QCS5430/QCS6490, IQ-9075/IQ-9100, IQ-8275/IQ-8300 |
| --- | --- |
| RSA Only | ECDSA, RSA |

The table lists the supported configuration by cryptographic algorithms.

Table : Configurations for cryptographic algorithms

| ‑ | ECDSA | RSA |
| --- | --- | --- |
| Key Size/Curve | SECP384R1 Curve | 2048, 4096 |
| Signature Algorithm Support | SHA384 | SHA256 |
| Exponent | NA | 65537 |

Note

The PK HASH used for fusing in QFPROM region is SHA-384 for all configurations, irrespective of the signature algorithm used.

## Generate a key pair for secure boot

Select one of the supported algorithms to enable secure boot on the device using either ECDSA or RSA.

> 
> 
> - Option 1: [Generate ECDSA root key and certificate](https://docs.qualcomm.com/doc/80-70020-11/topic/generate-keys-and-certificates.html#section-generate-ecdsa-root-key-certificate-lable).
> - Option 2: [Generate RSA client application key pair and certificate](https://docs.qualcomm.com/doc/80-70020-11/topic/generate-keys-and-certificates.html#section-enable-secure-boot-using-sectools-lable).

For support cryptographic algorithms see the [Cryptographic algorithms table](https://docs.qualcomm.com/doc/80-70020-11/topic/generate-keys-and-certificates.html#section-crypto-algorithm-tables).

Note

ECDSA is recommended over RSA for better security, if supported.

**Option 1: Generate ECDSA root key and certificate**

ECDSA offers superior security and performance compared to the RSA signature algorithm. As a result, the default configuration in SecTools supports ECDSA signing.

The following types of keys are created with ECDSA:
- The public key, which is accessible to everyone.
- The private key, which is only known to the owner of the key pair.

You can modify and run the following ECDSA-specific commands to generate the root key and certificate:

1. Go to the `OEM-KEYS` directory and generate the ECDSA root key and certificate:

cd ./OEM-KEYS
        
        openssl ecparam -genkey -name secp384r1 -outform PEM -out qpsa_rootca.key
        Copy to clipboard

openssl req -new -key qpsa_rootca.key -sha384 -out rootca_pem.crt -subj '/C=US/CN=Generated OEM Root CA/OU=CDMA Technologies/OU=General Use OEM Key (OEM should update all fields)/L=San Diego/O=SecTools/ST=California' -config opensslroot.cfg -x509 -days 7300 -set_serial 1
        Copy to clipboard

openssl x509 -in rootca_pem.crt -inform PEM -out qpsa_rootca.cer -outform DER
        Copy to clipboard
2. Generate the intermediate Certificate Authority (CA) key pair and certificate:

openssl ecparam -genkey -name secp384r1 -outform PEM -out qpsa_attestca.key
        Copy to clipboard

openssl req -new -key qpsa_attestca.key -out ca.CSR -subj '/C=US/ST=California/CN=Generated OEM Attestation CA/O=SecTools/L=San Diego' -config opensslroot.cfg -sha384
        Copy to clipboard

openssl x509 -req -in ca.CSR -CA rootca_pem.crt -CAkey qpsa_rootca.key -out ca_pem.crt -set_serial 1 -days 7300 -extfile v3.ext -sha384 -CAcreateserial
        Copy to clipboard

openssl x509 -inform PEM -in ca_pem.crt -outform DER -out qpsa_attestca.cer
        Copy to clipboard

**Option 2: Generate RSA client application key pair and certificate**

RSA is an encryption algorithm that uses a pair of keys to encrypt and decrypt data, ensuring secure data transmission.

A private key and a public key are created with RSA:

> 
> 
> - The public key is accessible to anyone.
> - The private key is only known to the owner of the key pair.

Either the public or private key can encrypt the data, and the other key decrypts it. Follow these steps to generate an RSA client application key pair and certificate.

1. To generate the root client application key pair and certificate, run the following
commands:

    The key size used is 2048. However, a key size of 4096 is also supported.

openssl genrsa -out qpsa_rootca.key 2048
        Copy to clipboard

openssl req -new -sha256 -key qpsa_rootca.key -x509 -out rootca_pem.crt -subj /C=US/ST=California/L="San Diego"/OU="General Use Test Key (for testing 13 only)"/OU="CDMA Technologies"/O=QUALCOMM/CN="QCT Root CA 1" -days 7300 -set_serial 1 -config opensslroot.cfg -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -sigopt digest:sha256
        Copy to clipboard

openssl x509 -in rootca_pem.crt -inform PEM -out qpsa_rootca.cer -outform DER
        Copy to clipboard

openssl x509 -text -inform DER -in qpsa_rootca.cer
        Copy to clipboard
2. To generate the attestation client application key pair and certificate, run the
following commands using RSA with a key size of 2048:

openssl genrsa -out qpsa_attestca.key 2048
        Copy to clipboard

openssl req -new -key qpsa_attestca.key -out attestca.csr -subj /C=US/ST=CA/L="San Diego"/OU="CDMA Technologies"/O=QUALCOMM/CN="QUALCOMM Attestation CA" -days 7300 -config opensslroot.cfg
        Copy to clipboard

openssl x509 -req -in attestca.csr -CA rootca_pem.crt -CAkey qpsa_rootca.key -out attestca_pem.crt -set_serial 5 -days 7300 -extfile v3.ext –sha256 -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -sigopt digest:sha256
        Copy to clipboard

openssl x509 -inform PEM -in attestca_pem.crt -outform DER -out qpsa_attestca.cer
        Copy to clipboard

## Generate SHA-384 hash for RSA and ECDSA

The SHA-384 hash is crucial in cryptographic applications for several reasons, including enhancing security strength, creating digital signatures, ensuring compliance with standards, and future-proofing. SHA-384 will be used as the RoT and ensure the authenticity and integrity of software images

To generate the SHA-384 hash of the root certificate, run the following command:

> 
> 
> openssl dgst -sha384 qpsa_rootca.cer >sha384rootcert.txt
>     Copy to clipboard

## Next steps

- To ensure the authenticity and integrity of software images and to write a complete software image, see [Sign and flash the images](https://docs.qualcomm.com/doc/80-70020-11/topic/sign-and-flash-images.html#sign-and-flash-images).
- To enforce strict access controls, see [Enable SELinux](https://docs.qualcomm.com/doc/80-70020-11/topic/enable-selinux.html#enable-selinux).

Last Published: Apr 14, 2026

[Previous Topic
Set the QFPROM fuses](https://docs.qualcomm.com/bundle/publicresource/80-70020-11/topics/appendix-fuse-configurations.md) [Next Topic
Sign and flash the images](https://docs.qualcomm.com/bundle/publicresource/80-70020-11/topics/sign-and-flash-images.md)