6#include "coseparser_p.h"
7#include "cborutils_p.h"
10#include <openssl/verify_p.h>
11#include <openssl/x509loader_p.h>
14#include <QCborStreamReader>
15#include <QCborStreamWriter>
19#include <openssl/bn.h>
20#include <openssl/evp.h>
21#include <openssl/err.h>
22#include <openssl/pem.h>
25 CoseHeaderAlgorithm = 1,
30 CoseAlgorithmECDSA_SHA256 = -7,
31 CoseAlgorithmECDSA_SHA384 = -35,
32 CoseAlgorithmECDSA_SHA512 = -36,
33 CoseAlgorithmRSA_PSS_256 = -37,
34 CoseAlgorithmRSA_PSS_384 = -38,
35 CoseAlgorithmRSA_PSS_512 = -39,
45 qCWarning(
Log) <<
"wrong COSE tag:" << reader.toTag();
50 if (!reader.isArray()) {
54 reader.enterContainer();
55 m_protectedParams = CborUtils::readByteArray(reader);
57 const auto algorithm = params.toMap().value(CoseHeaderAlgorithm).toInteger();
58 m_kid = params.toMap().value(CoseHeaderKid).toByteArray();
60 if (m_kid.isEmpty()) {
61 m_kid = params.toMap().value(CoseHeaderKid).toByteArray();
63 m_payload = CborUtils::readByteArray(reader);
64 m_signature = CborUtils::readByteArray(reader);
69 qCWarning(
Log) <<
"unable to find certificate for key id:" << m_kid.toHex();
70 m_signatureState = UnknownCertificate;
74 const auto certData = certFile.readAll();
75 const auto cert = X509Loader::readFromDER(certData);
77 qCWarning(
Log) <<
"failed to read X509 certificate";
78 m_signatureState = UnknownCertificate;
81 const openssl::evp_pkey_ptr pkey(X509_get_pubkey(cert.get()));
83 qCWarning(
Log) <<
"failed to load public key";
84 m_signatureState = UnknownCertificate;
90 case CoseAlgorithmECDSA_SHA256:
91 case CoseAlgorithmECDSA_SHA384:
92 case CoseAlgorithmECDSA_SHA512:
93 validateECDSA(pkey, algorithm);
95 case CoseAlgorithmRSA_PSS_256:
96 case CoseAlgorithmRSA_PSS_384:
97 case CoseAlgorithmRSA_PSS_512:
98 validateRSAPSS(pkey, algorithm);
101 qCWarning(
Log) <<
"signature algorithm not implemented yet:" << algorithm;
102 m_signatureState = UnsupportedAlgorithm;
112CoseParser::SignatureState CoseParser::signatureState()
const
114 return m_signatureState;
119 return m_certificate;
122void CoseParser::clear()
124 m_protectedParams.
clear();
131void CoseParser::validateECDSA(
const openssl::evp_pkey_ptr &pkey,
int algorithm)
133 const openssl::ec_key_ptr ecKey(EVP_PKEY_get1_EC_KEY(pkey.get()));
135 const EVP_MD *digest =
nullptr;
137 case CoseAlgorithmECDSA_SHA256:
138 digest = EVP_sha256();
140 case CoseAlgorithmECDSA_SHA384:
141 digest = EVP_sha384();
143 case CoseAlgorithmECDSA_SHA512:
144 digest = EVP_sha512();
149 const auto signedData = sigStructure();
150 m_signatureState = Verify::verifyECDSA(pkey, digest, signedData.constData(), signedData.size(), m_signature.constData(), m_signature.size()) ?
151 ValidSignature : InvalidSignature;
154void CoseParser::validateRSAPSS(
const openssl::evp_pkey_ptr &pkey,
int algorithm)
157 const EVP_MD *digest =
nullptr;
159 case CoseAlgorithmRSA_PSS_256:
160 digest = EVP_sha256();
162 case CoseAlgorithmRSA_PSS_384:
163 digest = EVP_sha384();
165 case CoseAlgorithmRSA_PSS_512:
166 digest = EVP_sha512();
170 const auto signedData = sigStructure();
171 uint8_t digestData[EVP_MAX_MD_SIZE];
172 uint32_t digestSize = 0;
173 EVP_Digest(
reinterpret_cast<const uint8_t*
>(signedData.constData()), signedData.size(), digestData, &digestSize, digest,
nullptr);
176 openssl::evp_pkey_ctx_ptr ctx(EVP_PKEY_CTX_new(pkey.get(),
nullptr));
177 if (!ctx || EVP_PKEY_verify_init(ctx.get()) <= 0) {
180 if (EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PSS_PADDING) <= 0 || EVP_PKEY_CTX_set_signature_md(ctx.get(), digest) <= 0) {
184 const auto verifyResult = EVP_PKEY_verify(ctx.get(),
reinterpret_cast<const uint8_t*
>(m_signature.constData()), m_signature.size(), digestData, digestSize);
185 switch (verifyResult) {
187 m_signatureState = InvalidSignature;
188 qCWarning(
Log) <<
"Failed to verify signature:" << ERR_error_string(ERR_get_error(),
nullptr);
191 m_signatureState = InvalidSignature;
194 m_signatureState = ValidSignature;
204 writer.startArray(4);
206 writer.append(m_protectedParams);
208 writer.append(m_payload);
QCborValue fromCbor(QCborStreamReader &reader)
QString fromUtf8(QByteArrayView str)