U
    c                     @   s  d dl Z d dlZd dlmZ d dlmZmZmZmZmZm	Z	m
Z
mZ d dlmZmZmZmZ d dlmZ d dlmZ d dlmZmZmZ d dlmZmZmZmZmZmZm Z  d d	l!m"Z" d d
l#m$Z$ d dl%m&Z&m'Z' d dl(m)Z)m*Z* d dl+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5 ddl6m7Z7 ddl8m9Z9m:Z: ddl;m<Z< ddl=m>Z> ddl?m@Z@mAZAmBZBmCZCmDZDmEZEmFZF ddlGmHZHmIZImJZJ dddddddddd d!d"gZKdd#lLmMZM eNeOZPe
d$eDd%ZQeRd&d'd(ZSejTejUd)d*d+ZVejUejWejXd,d-d"ZYdLejZejTe[e\ee& ee eeReRf d.d/dZ]ej^e0d0d1d Z_dMej^e\ee e`ee$ ee' e>d2d3dZadNejTee>ee$ ee' d4d5d6ZbeDddddfej^e	eQ e\ee`e>d7d8dZcejZee d9d:dZddOejZeReej^ d<d=dZeejZee\ d9d>dZfejZee\d?d@dZgej^ee e\dAdBdZheeji ejTeeee) eej f dCdDdEZkeeji ejTee ejUdFdGd!Zldddde7jmdfee\eejnejof ej^eeee>eEdHdIdZpdJdK ZqdS )P    N)datetime)IOIterableListOptionalTupleTypeTypeVarUnion)cmscoretspx509)InvalidSignature)hashes)CancelableAsyncIteratorValidationContextfind_valid_path)DisallowedAlgorithmErrorExpiredErrorInvalidCertificateErrorPathBuildingErrorPathValidationErrorRevokedErrorValidationError)TimeSlideFailure)ValidationPath)AlgorithmUsagePolicyPKIXValidationParams)ACValidationResultasync_validate_ac)
CMSExtractionErrorCMSStructuralErrorMultivaluedAttributeErrorNonexistentAttributeErrorSignedDataCertscheck_ess_certidextract_certificate_infoextract_signer_infofind_unique_cms_attributeget_pyca_cryptography_hash   )misc   )AdESFailureAdESIndeterminate   )errors)KeyUsageConstraints)CAdESSignerAttributeAssertionsCertifiedAttributesClaimedAttributesRevocationDetailsSignatureStatusStandardCMSSignatureStatusTimestampSignatureStatus)DEFAULT_ALGORITHM_USAGE_POLICYextract_message_digestvalidate_rawvalidate_sig_integrityasync_validate_cms_signaturecollect_timing_infovalidate_tst_signed_dataasync_validate_detached_cmscms_basic_validationcompute_signature_tst_digestextract_tst_dataextract_self_reported_tsextract_certs_for_validationcollect_signer_attr_statusvalidate_algorithm_protection)lift_iterable_async
StatusType)boundv2c              
   C   s   |rdnd}|rt jnt j}zt| |}|| W S  tk
rL   Y d S  tk
r } ztj	}t
jd|d|W 5 d }~X Y nX d S )NZsigning_certificate_v2Zsigning_certificatez3Wrong cardinality for signing certificate attributeZades_subindication)r   ZSigningCertificateV2ZSigningCertificater)   loaddumpr$   r#   r/   NO_SIGNING_CERTIFICATE_FOUNDr1   SignatureValidationError)signed_attrsrM   	attr_nameclsvalueeerr rY   G/tmp/pip-unpacked-wheel-0kb_yl26/pyhanko/sign/validation/generic_cms.py_grab_signing_cert_attrO   s    
r[   )certrS   c                 C   sf   t |dd}|d kr t |dd}|d kr,d S |d d }t| |sbtj}tjd| jj d|dd S )	NTrL   Fcertsr   zWSigning certificate attribute does not match selected signer's certificate for subject"z".rN   )r[   r&   r/   rQ   r1   rR   subjecthuman_friendly)r\   rS   attrZcertidrX   rY   rY   rZ   _check_signing_certificatee   s    
ra   )attrsclaimed_digest_algorithm_objclaimed_signature_algorithm_objc                 C   s   zt | d}W n2 tk
r&   d}Y n tk
r@   tdY nX |dk	r|d j}||jkrhtd|d j}|dkrtdn||jkrtddS )	a+  
    Internal API to validate the CMS algorithm protection attribute
    defined in :rfc:`6211`, if present.

    :param attrs:
        A CMS attribute list.
    :param claimed_digest_algorithm_obj:
        The claimed (i.e. unprotected) digest algorithm value.
    :param claimed_signature_algorithm_obj:
        The claimed (i.e. unprotected) signature algorithm value.
    :raises errors.CMSStructuralError:
        if multiple CMS protection attributes are present
    :raises errors.CMSAlgorithmProtectionError:
        if a mismatch is detected
    Zcms_algorithm_protectionNz4Multiple CMS algorithm protection attributes presentdigest_algorithmzCDigest algorithm does not match CMS algorithm protection attribute.signature_algorithmz<CMS algorithm protection attribute not valid for signed datazFSignature mechanism does not match CMS algorithm protection attribute.)r)   r$   r#   r"   nativer1   CMSAlgorithmProtectionError)rb   rc   rd   Zcms_algid_protectionZauth_digest_algorithmZsigned_sig_algorithmrY   rY   rZ   rH      s8     


)signer_infor\   expected_content_typeactual_digestalgorithm_usage_policy
time_indicreturnc              
   C   s  | d }| d }|d j }|dk	rz|j|||jd}	|	szd|d j  d}
|	jdk	rf|
d|	j d	7 }
tj|
|	jdkd
| d j }| d }|tjkrd}d}|}n| d 	 }|
 }d}zt|||d W nl tk
r } ztj|jtjdW 5 d}~X Y n8 tjk
r< } ztj|jtjdW 5 d}~X Y nX t|| zt|d}W n* ttfk
r   tjdtjdY nX |j }||krtjd| d| tjdt| }z t||||||||d d}W n tk
r   d}Y nX |dk	r||kn|}||fS )ae  
    Validate the integrity of a signature for a particular signerInfo object
    inside a CMS signed data container.

    .. warning::
        This function does not do any trust checks, and is considered
        "dangerous" API because it is easy to misuse.

    :param signer_info:
        A :class:`cms.SignerInfo` object.
    :param cert:
        The signer's certificate.

        .. note::
            This function will not attempt to extract certificates from
            the signed data.
    :param expected_content_type:
        The expected value for the content type attribute (as a Python string,
        see :class:`cms.ContentType`).
    :param actual_digest:
        The actual digest to be matched to the message digest attribute.
    :param algorithm_usage_policy:
        Algorithm usage policy.
    :param time_indic:
        Time indication for the production of the signature.
    :return:
        A tuple of two booleans. The first indicates whether the provided
        digest matches the value in the signed attributes.
        The second indicates whether the signature of the digest is valid.
    rf   re   	algorithmN)Zmoment
public_keyzThe algorithm z, is not allowed by the current usage policy.z	 Reason: .)Z	permanent	signaturerS   TF)rc   rd   rN   content_typezQContent type not found in signature, or multiple content-type attributes present.zContent type z did not match expected value )	prehashedalgorithm_policyrm   )rg   Zsignature_algorithm_allowedrp   Zfailure_reasonr1   r   Znot_allowed_afterr   ZVOIDZuntagrP   rH   r"   rR   failure_messager.   FORMAT_FAILURErh   r/   ZGENERICra   r)   r$   r#   r;   r<   r   )ri   r\   rj   rk   rl   rm   rf   Zdigest_algorithm_objmd_algorithmZalgo_allowedmsgrr   Zsigned_attrs_origZembedded_digestrt   signed_datarS   rW   rs   validintactrY   rY   rZ   r=      s    (

 

	
 
 
     
)rz   rn   c                 C   sV   zt | }|j}W n$ tk
r6   tjdtjdY nX t| }|d }t|| |S )a  
    Extract certificates from a CMS signed data object for validation purposes,
    identifying the signer's certificate in accordance with ETSI EN 319 102-1,
    5.2.3.4.

    :param signed_data:
        The CMS payload.
    :return:
        The extracted certificates.
    z,signer certificate not included in signaturerN   rS   )	r'   signer_certr!   r1   rR   r/   rQ   r(   ra   )rz   	cert_infor\   ri   rS   rY   rY   rZ   rF   H  s    

)rz   
raw_digestvalidation_contextstatus_kwargsvalidation_pathpkix_validation_paramskey_usage_settingsc             
      s  t | }t| }|j}	|j}
d}d}|dk	r8|j}|j}|p@t }|dkrNt}|d }|d j}|d d j}| d }|d j}|dkrt	|d }t
|}t|}|| | }zt||	||||d\}}W n< tk
r } ztjd	|j tjd
|W 5 d}~X Y nX d } }}|rzP|j|
 |dk	rHt|g}n|j|	}t|	||||dI dH \}}}W n8 tk
r } ztjd|d tj }W 5 d}~X Y nX |pi }|j|||	|||||d |S )z
    Perform basic validation of CMS and PKCS#7 signatures in isolation
    (i.e. integrity and trust checks).

    Internal API.
    Nrf   ro   re   encap_content_infors   content)rj   rk   rl   rm   zCMS structural error: rN   )r   pathsr   z&Processing error in validation processexc_info)r|   r{   Zsigning_certrx   Zpkcs7_signature_mechanismZtrust_problem_indicr   Zrevocation_details)!r(   rF   r}   other_certsru   Zbest_signature_timer   r:   rg   bytesr*   r   Hashupdatefinalizer=   r"   r1   rR   rv   r.   rw   certificate_registryregister_multiplerI   Zpath_builderZasync_build_paths_lazyvalidate_cert_usage
ValueErrorloggererrorr/   !CERTIFICATE_CHAIN_GENERAL_FAILURE)rz   r   r   r   r   r   r   ri   r~   r\   r   ru   rm   rf   Z	mechanismrx   ecirj   rawZmd_specmdr|   r{   rW   ades_statuspathrevo_detailsr   rY   rY   rZ   rB   f  s    




   
  
    )r\   r   r   r   r   c           
         sV    fdd}t | I dH \}}}|dk	rL jj}	td|	 d |||fS )zE
    Low-level certificate validation routine.
    Internal API.
    c                      s       t dI d H S )N)r   r   )validater   rY   r\   r   r   r   r   rY   rZ   _check  s    
 z#validate_cert_usage.<locals>._checkNzChain of trust validation for z failed.)handle_certvalidator_errorsr^   r_   r   warning)
r\   r   r   r   r   r   r   r   r   ZsubjrY   r   rZ   r     s    	r   rz   Z
status_clsr   r   r   r   c                    s,   | |}t| ||||dI dH }|f |S )a  
    Validate a CMS signature (i.e. a ``SignedData`` object).

    :param signed_data:
        The :class:`.asn1crypto.cms.SignedData` object to validate.
    :param status_cls:
        Status class to use for the validation result.
    :param raw_digest:
        Raw digest, computed from context.
    :param validation_context:
        Validation context to validate the signer's certificate.
    :param status_kwargs:
        Other keyword arguments to pass to the ``status_class`` when reporting
        validation results.
    :param key_usage_settings:
        A :class:`.KeyUsageConstraints` object specifying which key usages
        must or must not be present in the signer's certificate.
    :return:
        A :class:`.SignatureStatus` object (or an instance of a proper subclass)
    )r   N)default_usage_constraintsrB   r   rY   rY   rZ   r>     s       )ri   rn   c              	   C   s8   z| d }t |d}|jW S  ttfk
r2   Y nX dS )a  
    Extract self-reported timestamp (from the ``signingTime`` attribute)

    Internal API.

    :param signer_info:
        A ``SignerInfo`` value.
    :return:
        The value of the ``signingTime`` attribute as a ``datetime``, or
        ``None``.
    rS   Zsigning_timeN)r)   rg   r$   r#   )ri   sastrY   rY   rZ   rE     s    
F)ri   signedrn   c              	   C   sV   z8|r| d }t |d}n| d }t |d}|d }|W S  ttfk
rP   Y nX dS )a  
    Extract signed data associated with a timestamp token.

    Internal API.

    :param signer_info:
        A ``SignerInfo`` value.
    :param signed:
        If ``True``, look for a content timestamp (among the signed
        attributes), else look for a signature timestamp (among the unsigned
        attributes).
    :return:
        The ``SignedData`` value found, or ``None``.
    rS   Zcontent_time_stampZunsigned_attrsZsignature_time_stamp_tokenr   N)r)   r$   r#   )ri   r   r   ZtstZuatst_signed_datarY   rY   rZ   rD     s    
c                 C   sf   t | }|dkrdS |d }|d jd }|d d j}| d j}t|}t|}|| | S )a.  
    Compute the digest of the signature according to the message imprint
    algorithm information in a signature timestamp token.

    Internal API.

    :param signer_info:
        A ``SignerInfo`` value.
    :return:
        The computed digest, or ``None`` if there is no signature timestamp.
    Nr   r   message_imprintZhash_algorithmro   rr   )rD   parsedrg   r*   r   r   r   r   )ri   Ztst_datar   miZtst_md_algorithmZsignature_bytesZtst_md_specr   rY   rY   rZ   rC   0  s    


)ri   ts_validation_contextr   c                    s   i }t | }|dk	r||d< t| dd}|dk	rXt||t| I dH }tf |}||d< t| dd}|dk	rt|||dI dH }	tf |	}
|
|d< |S )	a  
    Collect and validate timing information in a ``SignerInfo`` value.
    This includes the ``signingTime`` attribute, content timestamp information
    and signature timestamp information.

    :param signer_info:
        A ``SignerInfo`` value.
    :param ts_validation_context:
        The timestamp validation context to validate against.
    :param raw_digest:
        The raw external message digest bytes (only relevant for the
        validation of the content timestamp token, if there is one)
    Nsigner_reported_dtF)r   Ztimestamp_validityT)expected_tst_imprintZcontent_timestamp_validity)rE   rD   r@   rC   r9   )ri   r   r   r   r   r   Ztst_validity_kwargsZtst_validityZcontent_tst_signed_dataZcontent_tst_validity_kwargsZcontent_tst_validityrY   rY   rZ   r?   O  s2     

 )r   r   r   c           	         s   d}| d d }t |tjr"|j}t |tjs>tjdtj	d|d j
}t }t| |d|i|dI dH }|d	 d
 j
}||krtd|  d|  d d|d< |S )a  
    Validate the ``SignedData`` of a time stamp token.

    :param tst_signed_data:
        The ``SignedData`` value to validate; must encapsulate a ``TSTInfo``
        value.
    :param validation_context:
        The validation context to validate against.
    :param expected_tst_imprint:
        The expected message imprint value that should be contained in
        the encapsulated ``TSTInfo``.
    :return:
        Keyword arguments for a :class:`.TimeStampSignatureStatus`.
    Nr   r   z'SignedData does not encapsulate TSTInforN   Zgen_time	timestamp)r   r   r   r   Zhashed_messagezTimestamp token imprint is z, but expected rq   Fr|   )
isinstancer   ZParsableOctetStringr   r   ZTSTInfor1   rR   r.   rw   rg   r9   r   rB   r   r   hex)	r   r   r   Ztst_infoZtst_info_bytesr   Zku_settingsr   Ztst_imprintrY   rY   rZ   r@   ~  s0    
 )acsr}   r   rn   c                    sz    fdd| D }g }g }t |D ]J}z||I d H  W q& ttfk
rn } z|| W 5 d }~X Y q&X q&||fS )Nc                    s   g | ]}t | d qS ))Zholder_cert)r    ).0acr}   r   rY   rZ   
<listcomp>  s   z+process_certified_attrs.<locals>.<listcomp>)asyncioZas_completedappendr   r   )r   r}   r   jobsresultsr1   ZjobrW   rY   r   rZ   process_certified_attrs  s    r   sd_attr_certificatesr}   r   sd_signed_attrsc              
      s  zt |d}W nN tk
r&   d }Y n8 tk
r\ } ztjt|tjd|W 5 d }~X Y nX i }d }d }|d k	rN|d }	t	t
|	tjs|	nd}
|d }d}t
|tjsdd |D }t|t|k}|d k	rt|||}|I d H \}}|d k	rt|}nd }|pt
|d	 tj }|d k	r:|r:td
 t|
|||d|d< |d k	rt| ||I d H \}}|r~|| |r|| t||d< ||d< |S )NZsigner_attributes_v2rN   Zclaimed_attributesrY   Zcertified_attributes_v2Fc                 S   s   g | ]}|j d kr|jqS )Z	attr_cert)nameZchosen)r   r`   rY   rY   rZ   r     s   
z.collect_signer_attr_status.<locals>.<listcomp>Zsigned_assertionszCAdES signer attributes with externally certified assertions for which no validation method is available. This may affect signature semantics in unexpected ways.)Zclaimed_attrsZcertified_attrsac_validation_errsZunknown_attrs_presentZcades_signer_attrsZac_attrsr   )r)   r$   r#   r1   rR   strr.   rw   r5   from_iterabler   r   ZVoidlenr   r4   Zfrom_resultsr   r   r3   extend)r   r}   r   r   Zsigner_attrsrW   resultZcades_ac_resultsZcades_ac_errorsZclaimed_asn1ZclaimedZcertified_asn1Zunknown_cert_attrsZ	cades_acsZval_jobZ	certifiedZunknown_attrsZ
ac_resultsZ	ac_errorsrY   rY   rZ   rG     s~     
  
 

  

)
input_datarz   signer_validation_contextr   ac_validation_contextr   rn   c                    s  |dkr|}t |}|d d j}	tt|	}
t| trF|
|  n@t| tj	tj
frl|
t| d  nt|}tj|| |
|d |
 }t|||dI dH }t|}t|||||dI dH }t|}|dk	r|j|j |t|j|j||d d	I dH  tf |S )
a  
    .. versionadded: 0.9.0

    .. versionchanged: 0.11.0
        Added ``ac_validation_context`` param.

    Validate a detached CMS signature.

    :param input_data:
        The input data to sign. This can be either a :class:`bytes` object,
        a file-like object or a :class:`cms.ContentInfo` /
        :class:`cms.EncapsulatedContentInfo` object.

        If a CMS content info object is passed in, the `content` field
        will be extracted.
    :param signed_data:
        The :class:`cms.SignedData` object containing the signature to verify.
    :param signer_validation_context:
        Validation context to use to verify the signer certificate's trust.
    :param ts_validation_context:
        Validation context to use to verify the TSA certificate's trust, if
        a timestamp token is present.
        By default, the same validation context as that of the signer is used.
    :param ac_validation_context:
        Validation context to use to validate attribute certificates.
        If not supplied, no AC validation will be performed.

        .. note::
            :rfc:`5755` requires attribute authority trust roots to be specified
            explicitly; hence why there's no default.
    :param key_usage_settings:
        Key usage parameters for the signer.
    :param chunk_size:
        Chunk size to use when consuming input data.
    :param max_read:
        Maximal number of bytes to read from the input stream.
    :return:
        A description of the signature's status.
    Nre   ro   r   )max_read)r   r   )r   r   r   r   rS   r   )r(   rg   r   r   r*   r   r   r   r   ContentInfoEncapsulatedContentInfo	bytearrayr,   Zchunked_digestr   r?   r8   r   rB   r'   r   r   r   rG   Zattribute_certsr}   )r   rz   r   r   r   r   
chunk_sizer   ri   re   hZtemp_bufZdigest_bytesr   r~   rY   rY   rZ   rA   !  sP    2
  
c              
      s6  d}zdd| I dH fW S  t k
rP } ztj|j|d tj}W 5 d}~X Y n tk
r } ztj|j|d tj}W 5 d}~X Y n tk
r } z|j	dkrtj
}ntj}W 5 d}~X Y nj tk
r8 } zXt|j |jrtj}n:|jrtj}td|j|jd}ntj}td|j|jd}W 5 d}~X Y n tk
rn } ztjd|d tj}W 5 d}~X Y n tk
r } z.t|j |js|jrtj}ntj}W 5 d}~X Y nr tk
r } ztj|j|d tj}W 5 d}~X Y n: tk
r* } ztj|j|d tj}W 5 d}~X Y nX ||dfS )z
    Internal error handling function that maps certvalidator errors
    to AdES status indications.

    :param coro:
    :return:
    Nr   F)Z
ca_revokedZrevocation_dateZrevocation_reasonTzFailed to build path)r   r   r   Zfailure_msgr/   ZCHAIN_CONSTRAINTS_FAILUREr   ZNO_POEr   Zbanned_sinceZCRYPTO_CONSTRAINTS_FAILUREZ!CRYPTO_CONSTRAINTS_FAILURE_NO_POEr   Zis_side_validationr   Z
is_ee_certZREVOKED_NO_POEr6   Zrevocation_dtreasonZREVOKED_CA_NO_POEr   ZNO_CERTIFICATE_CHAIN_FOUNDr   ZOUT_OF_BOUNDS_NO_POEr   r   )coror   rW   r   rY   rY   rZ   r   }  sZ    
  r   )NN)NNNNN)N)F)rr   loggingr   typingr   r   r   r   r   r   r	   r
   Z
asn1cryptor   r   r   r   Zcryptography.exceptionsr   Zcryptography.hazmat.primitivesr   Zpyhanko_certvalidatorr   r   r   Zpyhanko_certvalidator.errorsr   r   r   r   r   r   r   Z pyhanko_certvalidator.ltv.errorsr   Zpyhanko_certvalidator.pathr   Z!pyhanko_certvalidator.policy_declr   r   Zpyhanko_certvalidator.validater   r    Zpyhanko.sign.generalr!   r"   r#   r$   r%   r&   r'   r(   r)   r*   Z	pdf_utilsr,   Zades.reportr.   r/    r1   settingsr2   statusr3   r4   r5   r6   r7   r8   r9   utilsr:   r;   r<   __all__Zpdf_utils.miscrI   	getLogger__name__r   rJ   boolr[   ZCertificateZCMSAttributesra   ZDigestAlgorithmZSignedDigestAlgorithmrH   Z
SignerInfor   r   r=   Z
SignedDatarF   dictrB   r   r>   rE   rD   rC   r?   r@   ZAttributeCertificateV2	Exceptionr   rG   ZDEFAULT_CHUNK_SIZEr   r   rA   r   rY   rY   rY   rZ   <module>   s  ($	0$	      	
:  
       _ $01d \