> ## Documentation Index
> Fetch the complete documentation index at: https://dragonwingdocs.qualcomm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 生成密钥和证书

## **生成本地（不安全）根密钥和证书**

版本 3（v3 和 v3\_attest）扩展定义了证书格式并建立证书颁发机构（CA）。此过程允许你创建一个本地 CA，其特定属性和约束由 v3 扩展设置，从而可以为测试和开发目的颁发证书。

按照以下步骤生成本地根密钥和证书。

1. 使用以下示例 OpenSSL 配置文件创建 `opensslroot.cfg`：
   OpenSSL 是用于安全套接字层（SSL）和传输层安全（TLS）协议的开源工具包，提供加密功能和命令行工具。
   以下示例 OpenSSL 配置文件用于生成证书请求和管理证书颁发机构（CA）。
   > > ```text theme={null}
   > > #
   > > #  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
   > > ```
   >
   > **注意**
   >
   > 在 Windows 平台上运行任何 OpenSSL 命令时，如果出现以下错误：
   >
   > > * Can't load /home/slua\_xxxx/.rnd into RNG.
   > >   > *xxxx:error:xxxx:random number generator:RAND\_load\_file:Can't open file:crypto/rand/randfile.c:98:Filename=/home/slua\_xxxx/.rnd*
   > >
   > > * Can't write random bytes.
   > >
   > > > *xxxx:error:xxxx:random number generator:RAND\_write\_file:Can't open file:crypto/rand/randfile.c:233:Filename=/home/slua\_xxxx/.rnd*
   >
   > 请从 opensslroot.cfg 文件中注释掉以下行：
   >
   > > RANDFILE = \$ENV::HOME/.rnd
2. 要创建 `v3.ext` 和 `v3_attest.ext` 扩展，请使用以下内容：
   * `v3.ext`：此扩展可在 [/docs/manmaster/man5/x509v3\_config.html (](https://www.openssl.org/docs/manmaster/man5/x509v3_config.html)[OpenSSL.org](http://OpenSSL.org)[)](https://www.openssl.org/docs/manmaster/man5/x509v3_config.html) 中找到，并包含以下设置：
     ```text theme={null}
     authorityKeyIdentifier=keyid,issuer
     subjectKeyIdentifier=hash
     basicConstraints=CA:true,pathlen:0
     keyUsage=keyCertSign
     ```
   * `v3_attest.ext`：此扩展可在 [/docs/manmaster/man5/x509v3\_config.html (](https://www.openssl.org/docs/manmaster/man5/x509v3_config.html)[OpenSSL.org](http://OpenSSL.org)[)](https://www.openssl.org/docs/manmaster/man5/x509v3_config.html) 中找到，并包含以下设置：
     ```text theme={null}
     authorityKeyIdentifier=keyid,issuer
     basicConstraints=CA:FALSE,pathlen:0
     keyUsage=digitalSignature
     extendedKeyUsage=codeSigning
     ```
3. 准备环境，创建名为 OEM-KEYS 的目录，以便在一个位置生成所有证书和密钥。
   * 对于 Linux，请使用以下命令：
     ```text theme={null}
     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
     ```
   * 对于 Windows，请将 `opensslroot.cfg`、`v3.ext` 和 `v3_attest.ext` 复制到 OEM-KEYS 目录。

下表列出了支持的加密算法。

**表：加密算法**

| **IQ-615** | **QCS5430/QCS6490、IQ-9075/IQ-9100、IQ-8275/IQ-8300** |
| :--------: | :-------------------------------------------------: |
|    仅 RSA   |                      ECDSA、RSA                      |

下表列出了各加密算法支持的配置。

**表：加密算法的配置**

|  **‑**  |   **ECDSA**  |  **RSA**  |
| :-----: | :----------: | :-------: |
| 密钥大小/曲线 | SECP384R1 曲线 | 2048、4096 |
|  签名算法支持 |    SHA384    |   SHA256  |
|    指数   |      NA      |   65537   |

**注意**

无论使用哪种签名算法，用于在 QFPROM 区域熔断的 PK HASH 在所有配置中均为 SHA-384。

## **为安全启动生成密钥对**

选择其中一种受支持的算法，使用 ECDSA 或 RSA 在设备上启用安全启动。

> * 选项 1：[生成 ECDSA 根密钥和证书](./generate-keys-and-certificates#option-1-generate-ecdsa-root-key-and-certificate)。
> * 选项 2：[生成 RSA 客户端应用密钥对和证书](./generate-keys-and-certificates#option-2-generate-rsa-key-pair-and-certificate)。

有关支持的加密算法，请参阅[加密算法表](./generate-keys-and-certificates#generate-a-key-pair-for-secure-boot)。

**注意**

如果支持，建议优先使用 ECDSA 而非 RSA，以获得更好的安全性。

### **选项 1：生成 ECDSA 根密钥和证书**

与 RSA 签名算法相比，ECDSA 提供更高的安全性和性能。因此，SecTools 中的默认配置支持 ECDSA 签名。

使用 ECDSA 会创建以下类型的密钥：- 公钥，所有人都可以访问。- 私钥，仅密钥对的所有者知道。

你可以修改并运行以下 ECDSA 专用命令来生成根密钥和证书：

1. 进入 `OEM-KEYS` 目录并生成 ECDSA 根密钥和证书：
   ```text theme={null}
   cd ./OEM-KEYS
   openssl ecparam -genkey -name secp384r1 -outform PEM -out qpsa_rootca.key
   ```
   ```text theme={null}
   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
   ```
   ```text theme={null}
   openssl x509 -in rootca_pem.crt -inform PEM -out qpsa_rootca.cer -outform DER
   ```
2. 生成中间证书颁发机构（CA）密钥对和证书：
   ```text theme={null}
   openssl ecparam -genkey -name secp384r1 -outform PEM -out qpsa_attestca.key
   ```
   ```text theme={null}
   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
   ```
   ```text theme={null}
   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
   ```
   ```text theme={null}
   openssl x509 -inform PEM -in ca_pem.crt -outform DER -out qpsa_attestca.cer
   ```

### **选项 2：生成 RSA 密钥对和证书**

RSA 签名算法使用非对称密钥（公钥/私钥）来验证消息的真实性和完整性。

使用 RSA 会创建私钥和公钥：

> * 公钥任何人都可以访问。
> * 私钥仅密钥对的所有者知道。

镜像使用 RSA 私钥链进行签名，并使用 OEM 公钥或证书链（锚定于熔丝中）进行验证。

按照以下步骤生成 RSA 密钥对和证书。

1. 要生成根客户端应用密钥对和证书，请运行以下命令：
   使用的密钥大小为 2048。但也支持 4096 的密钥大小。
   ```text theme={null}
   openssl genrsa -out qpsa_rootca.key 2048
   ```
   ```text theme={null}
   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
   .. note:: For OpenSSL > 3.x, don't pass the ``-sigopt digest:sha256`` option.
   ```
   ```text theme={null}
   openssl x509 -in rootca_pem.crt -inform PEM -out qpsa_rootca.cer -outform DER
   ```
   ```text theme={null}
   openssl x509 -text -inform DER -in qpsa_rootca.cer
   ```
2. 要生成认证客户端应用密钥对和证书，请使用密钥大小为 2048 的 RSA 运行以下命令：
   ```text theme={null}
   openssl genrsa -out qpsa_attestca.key 2048
   ```
   ```text theme={null}
   openssl req -new -key qpsa_attestca.key -out attestca.csr -subj "/C=US/ST=California/L=San Diego/OU=CDMA Technologies/O=QUALCOMM/CN=QUALCOMM Attestation CA" -days 7300 -config opensslroot.cfg
   ```
   ```text theme={null}
   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
   ```
   **注意**
   对于 OpenSSL > 3.x，请勿传递 `-sigopt digest:sha256` 选项。
   ```text theme={null}
   openssl x509 -inform PEM -in attestca_pem.crt -outform DER -out qpsa_attestca.cer
   ```

## **为 RSA 和 ECDSA 生成 SHA-384 哈希**

SHA-384 哈希在加密应用中至关重要，原因包括增强安全强度、创建数字签名、确保符合标准以及面向未来。SHA-384 将用作 RoT，并确保软件镜像的真实性和完整性

要生成根证书的 SHA-384 哈希，请运行以下命令：

> ```text theme={null}
> openssl dgst -sha384 qpsa_rootca.cer >sha384rootcert.txt
> ```

## **后续步骤**

* 要确保软件镜像的真实性和完整性并写入完整的软件镜像，请参阅[签名并烧写镜像](./sign-and-flash-the-images)。
* 要通过仅允许烧录经过数字签名的镜像来确保设备安全，请参阅[执行 VIP 烧写](./perform-vip-flashing)。
