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

# 生成密钥和证书

## **生成本地(不安全)根密钥和证书**

版本 3(v3 和 v3\_attest)扩展定义了证书格式并建立了证书颁发机构(CA)。此过程允许您创建一个具有由 v3 扩展设置的特定属性和约束的本地 CA,从而可以出于测试和开发目的颁发证书。

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

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. 要生成认证(attestation)客户端应用程序密钥对和证书,请使用密钥大小为 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)。
