#include "asn1/ASN1Util.h" #include "SecureMessagingResponse.h" #include #include #include using namespace governikus; IMPLEMENT_STACK_OF(ASN1_OCTET_STRING) ASN1_OBJECT * Asn1ObjectUtil::parseFrom(const QByteArray &pOidAsText) { return OBJ_txt2obj(pOidAsText.constData(), 1); } QByteArray Asn1ObjectUtil::convertTo(const ASN1_OBJECT* pAsn1Object) { if (pAsn1Object == nullptr) { return QByteArray(); } /* * According to OpenSSL's documentation on OBJ_nid2obj: * " A buffer length of 80 should be more than enough to handle any OID encountered in practice." */ char buf[80] = {}; if (OBJ_obj2txt(buf, sizeof(buf), pAsn1Object, 1) == sizeof(buf)) { qCritical() << "The OID may not fit into the given array, just return an empty string"; return QByteArray(); } return QByteArray(buf); } void Asn1OctetStringUtil::setValue(const QByteArray& pValue, ASN1_OCTET_STRING* pAsn1OctetString) { ASN1_OCTET_STRING_set(pAsn1OctetString, reinterpret_cast(pValue.data()), pValue.length()); } QByteArray Asn1OctetStringUtil::getValue(ASN1_OCTET_STRING* pAsn1OctetString) { if (pAsn1OctetString == nullptr) { return QByteArray(); } return QByteArray(reinterpret_cast(pAsn1OctetString->data), pAsn1OctetString->length); } void Asn1StringUtil::setValue(const QString& pString, ASN1_STRING* pOut) { QByteArray bytes = pString.toUtf8(); ASN1_STRING_set(pOut, bytes.data(), bytes.length()); } QString Asn1StringUtil::getValue(ASN1_STRING* pString) { if (pString == nullptr) { return QString(); } unsigned char* buf; int buf_len = ASN1_STRING_to_UTF8(&buf, pString); QString result; if (buf_len > 0) { result = QString::fromUtf8(reinterpret_cast(buf), buf_len); OPENSSL_free(buf); } return result; } QByteArray Asn1TypeUtil::encode(ASN1_TYPE* pAny) { if (pAny == nullptr) { return QByteArray(); } unsigned char* buf = nullptr; int buf_len = i2d_ASN1_TYPE(pAny, &buf); QByteArray result; if (buf_len > 0) { result = QByteArray(reinterpret_cast(buf), buf_len); OPENSSL_free(buf); } return result; } QByteArray Asn1IntegerUtil::getValue(const ASN1_INTEGER* pInteger) { if (pInteger == nullptr) { return QByteArray(); } return QByteArray(reinterpret_cast(pInteger->data), pInteger->length); } QByteArray Asn1BCDDateUtil::convertFromQDateToUnpackedBCD(QDate pDate) { QByteArray aBCD = pDate.toString(QStringLiteral("yyMMdd")).toLocal8Bit(); if (aBCD.length() != 6) { qCritical() << "Invalid date length."; return QByteArray(); } // convert to unpacked BCD digits for (int i = 0; i <= 5; i++) { aBCD[i] = static_cast(aBCD[i] - 0x30); } return aBCD; } QDate Asn1BCDDateUtil::convertFromUnpackedBCDToQDate(ASN1_OCTET_STRING* pDateBCD) { if (pDateBCD == nullptr) { qCritical() << "Date pointer null."; return QDate(); } if (pDateBCD->length != 6) { qCritical() << "Invalid date length."; return QDate(); } int year = 2000 + pDateBCD->data[0] * 10 + pDateBCD->data[1]; int month = pDateBCD->data[2] * 10 + pDateBCD->data[3]; int day = pDateBCD->data[4] * 10 + pDateBCD->data[5]; return QDate(year, month, day); } QByteArray Asn1Util::encode(char pTagByte, const QByteArray& pData) { // 1. encode as ASN1_OCTET_STRING using our template utils // (in fact SM_CHECKSUM ::= [8E] IMPLICIT OCTET STRING) auto octetString = newObject(); Asn1OctetStringUtil::setValue(pData, octetString.data()); auto encodedOctetString = encodeObject(octetString.data()); // 2. replace the tag byte return encodedOctetString.replace(0, 1, QByteArray(1, pTagByte)); }