I fixed this on my own, through trial and error.
The instructions referenced above create three files:
- azure-iot-test-only.root.ca.cert.pem
- new-device.cert.pem
- new-device.key.pem
File 1 is uploaded to Azure and verified there.
Files 2 and 3 are used by the device.
During the TLS handshake when connecting to Azure Iot Hub, the server (Azure) sends a certificate which must be verified by the device. That's where it was failing to verify. I had included File 1 for this purpose (as the TLS ca-cert), but that doesn't work. Azure IoT Hub is sending a Baltimore based certificate, so the device needs a Baltimore cert to verify it. That is not clear in the instructions.
The Baltimore (and Digicert) pem files can be obtained with this script (with Bash on Linux):
#!/bin/bash
# Copyright (c) Microsoft Corporation. All rights reserved.
# SPDX-License-Identifier: MIT
# Copied from github.com/Azure/azure-sdk-for-c/blob/main/sdk/samples/iot/aziot_esp32/create_trusted_cert_header.sh
#
# to execute: sh create_trusted_cert_header.sh
set -x # Set trace on
set -o errexit # Exit if command failed
set -o nounset # Exit if variable not set
#set -o pipefail # Exit if pipe failed
command -v xxd >/dev/null 2>&1 || { echo >&2 "Please install xxd."; exit 1; }
wget https://cacerts.digicert.com/BaltimoreCyberTrustRoot.crt.pem -O ca1.pem
wget https://cacerts.digicert.com/DigiCertGlobalRootG2.crt.pem -O ca2.pem
cat ca1.pem > ca.pem
cat ca2.pem >> ca.pem
echo -n -e '\0' >> ca.pem
xxd -i ca.pem ca.h
My device can now complete the handshake and publish/subscribe with Azure IoT Hub