@@ -247,6 +247,97 @@ static void pkcs7_free_signer_info(mbedtls_pkcs7_signer_info *signer)
247247 signer -> issuer .next = NULL ;
248248}
249249
250+ static int pkcs7_get_authenticated_attributes (unsigned char * * p , unsigned char * end_signer ,
251+ mbedtls_pkcs7_signer_info * signer )
252+ {
253+ int ret ;
254+ unsigned char * end ;
255+ unsigned char * start_attr ;
256+ unsigned char * start_attr_type ;
257+ unsigned char * end_attr_value ;
258+ size_t attr_len ;
259+ size_t attr_type_len ;
260+ size_t attr_value_len ;
261+ size_t len ;
262+ int seen_content_type = 0 ;
263+ int seen_message_digest = 0 ;
264+
265+ ret = mbedtls_asn1_get_tag (p , end_signer , & signer -> auth_attributes_raw .len ,
266+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0 );
267+ if (ret == 0 ) {
268+ /*
269+ * Per RFC 2315 Section 9.3, if the authenticatedAttributes field is present, the
270+ * message digest is computed on the DER encoding of the Attributes value.
271+ * Canonically, the authenticatedAttributes tag would therefore be encoded as SET OF.
272+ */
273+ signer -> auth_attributes_raw .tag = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ;
274+ signer -> auth_attributes_raw .p = * p ;
275+ end = * p + signer -> auth_attributes_raw .len ;
276+
277+ while (* p != end ) {
278+ if ((ret = mbedtls_asn1_get_tag (p , end , & attr_len , MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE )) != 0 ) {
279+ return ret ;
280+ }
281+ start_attr = * p ;
282+
283+ if ((ret = mbedtls_asn1_get_tag (p , end , & attr_type_len , MBEDTLS_ASN1_OID )) != 0 ) {
284+ return ret ;
285+ }
286+ start_attr_type = * p ;
287+ * p += attr_type_len ;
288+
289+ if ((ret = mbedtls_asn1_get_tag (p , end , & attr_value_len , MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET )) != 0 ) {
290+ return ret ;
291+ }
292+ end_attr_value = * p + attr_value_len ;
293+
294+ if (!MBEDTLS_OID_CMP_RAW (MBEDTLS_OID_PKCS9_CONTENT_TYPE , start_attr_type , attr_type_len )) {
295+ if ((ret = mbedtls_asn1_get_tag (p , end_attr_value , & len , MBEDTLS_ASN1_OID )) != 0 ) {
296+ return ret ;
297+ }
298+
299+ if (MBEDTLS_OID_CMP_RAW (MBEDTLS_OID_PKCS7_DATA , * p , len )) {
300+ return MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO ;
301+ }
302+
303+ * p += len ;
304+
305+ if (* p != end_attr_value ) {
306+ return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA ;
307+ }
308+
309+ seen_content_type = 1 ;
310+ } else if (!MBEDTLS_OID_CMP_RAW (MBEDTLS_OID_PKCS9_MESSAGE_DIGEST , start_attr_type , attr_type_len )) {
311+ if ((ret = mbedtls_asn1_get_tag (p , end , & len , MBEDTLS_ASN1_OCTET_STRING )) != 0 ) {
312+ return ret ;
313+ }
314+
315+ signer -> auth_attributes .message_digest_raw .tag = MBEDTLS_ASN1_OCTET_STRING ;
316+ signer -> auth_attributes .message_digest_raw .len = len ;
317+ signer -> auth_attributes .message_digest_raw .p = * p ;
318+
319+ * p += len ;
320+
321+ if (* p != end_attr_value ) {
322+ return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA ;
323+ }
324+
325+ seen_message_digest = 1 ;
326+ } else {
327+ /* Unknown attribute type, skip attribute. */
328+ * p = start_attr + attr_len ;
329+ }
330+ }
331+
332+ if (!seen_content_type || !seen_message_digest ) {
333+ return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA ;
334+ }
335+ }
336+
337+ /* authenticatedAttributes are optional, don't fail if it's not present. */
338+ return 0 ;
339+ }
340+
250341/**
251342 * SignerInfo ::= SEQUENCE {
252343 * version Version;
@@ -260,8 +351,7 @@ static void pkcs7_free_signer_info(mbedtls_pkcs7_signer_info *signer)
260351 * [1] IMPLICIT Attributes OPTIONAL,
261352 * Returns 0 if the signerInfo is valid.
262353 * Return negative error code for failure.
263- * Structure must not contain vales for authenticatedAttributes
264- * and unauthenticatedAttributes.
354+ * Structure must not contain values for unauthenticatedAttributes.
265355 **/
266356static int pkcs7_get_signer_info (unsigned char * * p , unsigned char * end ,
267357 mbedtls_pkcs7_signer_info * signer ,
@@ -331,7 +421,11 @@ static int pkcs7_get_signer_info(unsigned char **p, unsigned char *end,
331421 goto out ;
332422 }
333423
334- /* Assume authenticatedAttributes is nonexistent */
424+ ret = pkcs7_get_authenticated_attributes (p , end_signer , signer );
425+ if (ret != 0 ) {
426+ goto out ;
427+ }
428+
335429 ret = pkcs7_get_digest_algorithm (p , end_signer , & signer -> sig_alg_identifier );
336430 if (ret != 0 ) {
337431 goto out ;
0 commit comments