Kaydet (Commit) 7339a3d3 authored tarafından Miklos Vajna's avatar Miklos Vajna

vcl mscrypto PDF sign: fix typo in GetDERLengthOfLength()

When id-aa-signingCertificateV2 had a value that was larger than 255
bytes, then the header size is expected to be 4 bytes, but it was only
3. The length part of the header is 3 bytes: one byte declaring the
length-of-length, and 3 bytes for the length. We added this additional
byte to the result too early, that way we counted that e.g. 278 (the
number) fits into a single uint8_t, which is not the case.

Also introduce named constants for some of the hardwired numbers in the
code for better readability.

Change-Id: I816236e5ac561c9d21bd9df703385ee2201482e7
üst b18b1e80
...@@ -6165,11 +6165,11 @@ size_t GetDERLengthOfLength(size_t nLength) ...@@ -6165,11 +6165,11 @@ size_t GetDERLengthOfLength(size_t nLength)
if(nLength > 127) if(nLength > 127)
{ {
// Long form means at least two bytes: the length of the length and the
// length itself.
++nRet;
while (nLength >> (nRet * 8)) while (nLength >> (nRet * 8))
++nRet; ++nRet;
// Long form means one additional byte: the length of the length and
// the length itself.
++nRet;
} }
return nRet; return nRet;
} }
...@@ -6186,12 +6186,21 @@ void WriteDERLength(SvStream& rStream, size_t nLength) ...@@ -6186,12 +6186,21 @@ void WriteDERLength(SvStream& rStream, size_t nLength)
} }
// 0x80 means that the we use the long form: the first byte is the length // 0x80 means that the we use the long form: the first byte is the length
// of length, not the actual length. // of length with the highest bit set to 1, not the actual length.
rStream.WriteUInt8(0x80 | (nLengthOfLength - 1)); rStream.WriteUInt8(0x80 | (nLengthOfLength - 1));
for (size_t i = 1; i < nLengthOfLength; ++i) for (size_t i = 1; i < nLengthOfLength; ++i)
rStream.WriteUInt8(nLength >> ((nLengthOfLength - i - 1) * 8)); rStream.WriteUInt8(nLength >> ((nLengthOfLength - i - 1) * 8));
} }
const unsigned nASN1_INTEGER = 0x02;
const unsigned nASN1_OCTET_STRING = 0x04;
const unsigned nASN1_NULL = 0x05;
const unsigned nASN1_OBJECT_IDENTIFIER = 0x06;
const unsigned nASN1_SEQUENCE = 0x10;
/// An explicit tag on a constructed value.
const unsigned nASN1_TAGGED_CONSTRUCTED = 0xa0;
const unsigned nASN1_CONSTRUCTED = 0x20;
/// Create payload for the 'signing-certificate' signed attribute. /// Create payload for the 'signing-certificate' signed attribute.
bool CreateSigningCertificateAttribute(vcl::PDFWriter::PDFSignContext& rContext, PCCERT_CONTEXT pCertContext, SvStream& rEncodedCertificate) bool CreateSigningCertificateAttribute(vcl::PDFWriter::PDFSignContext& rContext, PCCERT_CONTEXT pCertContext, SvStream& rEncodedCertificate)
{ {
...@@ -6277,42 +6286,40 @@ bool CreateSigningCertificateAttribute(vcl::PDFWriter::PDFSignContext& rContext, ...@@ -6277,42 +6286,40 @@ bool CreateSigningCertificateAttribute(vcl::PDFWriter::PDFSignContext& rContext,
size_t nESSCertIDv2s = 1 + GetDERLengthOfLength(nESSCertIDv2) + nESSCertIDv2; size_t nESSCertIDv2s = 1 + GetDERLengthOfLength(nESSCertIDv2) + nESSCertIDv2;
// Write SigningCertificateV2. // Write SigningCertificateV2.
rEncodedCertificate.WriteUInt8(0x30); rEncodedCertificate.WriteUInt8(nASN1_SEQUENCE | nASN1_CONSTRUCTED);
WriteDERLength(rEncodedCertificate, nESSCertIDv2s); WriteDERLength(rEncodedCertificate, nESSCertIDv2s);
// Write SEQUENCE OF ESSCertIDv2. // Write SEQUENCE OF ESSCertIDv2.
rEncodedCertificate.WriteUInt8(0x30); rEncodedCertificate.WriteUInt8(nASN1_SEQUENCE | nASN1_CONSTRUCTED);
WriteDERLength(rEncodedCertificate, nESSCertIDv2); WriteDERLength(rEncodedCertificate, nESSCertIDv2);
// Write ESSCertIDv2. // Write ESSCertIDv2.
rEncodedCertificate.WriteUInt8(0x30); rEncodedCertificate.WriteUInt8(nASN1_SEQUENCE | nASN1_CONSTRUCTED);
WriteDERLength(rEncodedCertificate, nAlgorithmIdentifier + nCertHash + nIssuerSerial); WriteDERLength(rEncodedCertificate, nAlgorithmIdentifier + nCertHash + nIssuerSerial);
// Write AlgorithmIdentifier. // Write AlgorithmIdentifier.
rEncodedCertificate.WriteUInt8(0x30); rEncodedCertificate.WriteUInt8(nASN1_SEQUENCE | nASN1_CONSTRUCTED);
WriteDERLength(rEncodedCertificate, nAlgorithm + nParameters); WriteDERLength(rEncodedCertificate, nAlgorithm + nParameters);
// Write algorithm. // Write algorithm.
rEncodedCertificate.WriteUInt8(0x06); rEncodedCertificate.WriteUInt8(nASN1_OBJECT_IDENTIFIER);
WriteDERLength(rEncodedCertificate, aSHA256.size()); WriteDERLength(rEncodedCertificate, aSHA256.size());
rEncodedCertificate.WriteBytes(aSHA256.data(), aSHA256.size()); rEncodedCertificate.WriteBytes(aSHA256.data(), aSHA256.size());
// Write parameters. // Write parameters.
rEncodedCertificate.WriteUInt8(0x05); rEncodedCertificate.WriteUInt8(nASN1_NULL);
rEncodedCertificate.WriteUInt8(0x00); rEncodedCertificate.WriteUInt8(0);
// Write certHash. // Write certHash.
rEncodedCertificate.WriteUInt8(0x04); rEncodedCertificate.WriteUInt8(nASN1_OCTET_STRING);
WriteDERLength(rEncodedCertificate, aHash.size()); WriteDERLength(rEncodedCertificate, aHash.size());
rEncodedCertificate.WriteBytes(aHash.data(), aHash.size()); rEncodedCertificate.WriteBytes(aHash.data(), aHash.size());
// Write IssuerSerial. // Write IssuerSerial.
rEncodedCertificate.WriteUInt8(0x30); rEncodedCertificate.WriteUInt8(nASN1_SEQUENCE | nASN1_CONSTRUCTED);
WriteDERLength(rEncodedCertificate, nGeneralNames + nCertificateSerialNumber); WriteDERLength(rEncodedCertificate, nGeneralNames + nCertificateSerialNumber);
// Write GeneralNames. // Write GeneralNames.
rEncodedCertificate.WriteUInt8(0x30); rEncodedCertificate.WriteUInt8(nASN1_SEQUENCE | nASN1_CONSTRUCTED);
WriteDERLength(rEncodedCertificate, nName); WriteDERLength(rEncodedCertificate, nName);
// Write Name. // Write Name.
// 0xa0 means we're writing an explicit tag on a constructed value, the rEncodedCertificate.WriteUInt8(nASN1_TAGGED_CONSTRUCTED | 4);
// rest is the tag number.
rEncodedCertificate.WriteUInt8(0xa0 | 4);
WriteDERLength(rEncodedCertificate, nIssuer); WriteDERLength(rEncodedCertificate, nIssuer);
rEncodedCertificate.WriteBytes(pIssuer, nIssuer); rEncodedCertificate.WriteBytes(pIssuer, nIssuer);
// Write CertificateSerialNumber. // Write CertificateSerialNumber.
rEncodedCertificate.WriteUInt8(0x02); rEncodedCertificate.WriteUInt8(nASN1_INTEGER);
WriteDERLength(rEncodedCertificate, nSerial); WriteDERLength(rEncodedCertificate, nSerial);
rEncodedCertificate.WriteBytes(aSerial.data(), aSerial.size()); rEncodedCertificate.WriteBytes(aSerial.data(), aSerial.size());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment