X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/914fc88e61be54aed6b18205ff2775b48793a3b6..866f8763175ff60e4fa455b92b5eb660a12fe6c7:/libsecurity_smime/lib/CMSDecoder.h diff --git a/libsecurity_smime/lib/CMSDecoder.h b/libsecurity_smime/lib/CMSDecoder.h new file mode 100644 index 00000000..8355d3ce --- /dev/null +++ b/libsecurity_smime/lib/CMSDecoder.h @@ -0,0 +1,418 @@ +/* + * Copyright (c) 2006-2016 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * CMSDecoder.h - decode, decrypt, and/or verify signatures of messages in the + * Cryptographic Message Syntax (CMS), per RFC 3852. + * + * See CMSEncoder.h for general information about CMS messages. + */ + +#ifndef _CMS_DECODER_H_ +#define _CMS_DECODER_H_ + +#include +#include +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +CF_ASSUME_NONNULL_BEGIN + +/* + * Opaque reference to a CMS decoder object. + * This is a CF object, with standard CF semantics; dispose of it + * with CFRelease(). + */ +typedef struct CF_BRIDGED_TYPE(id) _CMSDecoder *CMSDecoderRef; + +CFTypeID CMSDecoderGetTypeID(void); + +/* + * Status of signature and signer information in a signed message. + */ +typedef CF_ENUM(int32_t, CMSSignerStatus) { + kCMSSignerUnsigned = 0, /* message was not signed */ + kCMSSignerValid, /* message was signed and signature verify OK */ + kCMSSignerNeedsDetachedContent, /* message was signed but needs detached content + * to verify */ + kCMSSignerInvalidSignature, /* message was signed but had a signature error */ + kCMSSignerInvalidCert, /* message was signed but an error occurred in verifying + * the signer's certificate */ + kCMSSignerInvalidIndex /* specified signer index out of range */ +}; + +/* + * Create a CMSDecoder. Result must eventually be freed via CFRelease(). + */ +OSStatus CMSDecoderCreate(CMSDecoderRef * __nonnull CF_RETURNS_RETAINED cmsDecoderOut) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_11_0); + +/* + * Feed raw bytes of the message to be decoded into the decoder. Can be called + * multiple times. + * Returns errSecUnknownFormat upon detection of improperly formatted CMS + * message. + */ +OSStatus CMSDecoderUpdateMessage( + CMSDecoderRef cmsDecoder, + const void *msgBytes, + size_t msgBytesLen) + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_11_0); + +/* + * Indicate that no more CMSDecoderUpdateMessage() calls are forthcoming; + * finish decoding the message. + * Returns errSecUnknownFormat upon detection of improperly formatted CMS + * message. + */ +OSStatus CMSDecoderFinalizeMessage(CMSDecoderRef cmsDecoder) + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_11_0); + +/* + * A signed CMS message optionally includes the data which was signed. If the + * message does not include the signed data, caller specifies the signed data + * (the "detached content") here. + * + * This can be called either before or after the actual decoding of the message + * (via CMSDecoderUpdateMessage() and CMSDecoderFinalizeMessage()); the only + * restriction is that, if detached content is required, this function must + * be called befoere successfully ascertaining the signature status via + * CMSDecoderCopySignerStatus(). + */ +OSStatus CMSDecoderSetDetachedContent( + CMSDecoderRef cmsDecoder, + CFDataRef detachedContent) + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_11_0); + +/* + * Obtain the detached content specified in CMSDecoderSetDetachedContent(). + * Returns a NULL detachedContent if no detached content has been specified. + * Caller must CFRelease() the result. + */ +OSStatus CMSDecoderCopyDetachedContent( + CMSDecoderRef cmsDecoder, + CFDataRef * __nonnull CF_RETURNS_RETAINED detachedContentOut) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_11_0); + +/* + * Obtain the number of signers of a message. A result of zero indicates that + * the message was not signed. + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderGetNumSigners( + CMSDecoderRef cmsDecoder, + size_t *numSignersOut) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_11_0); + +/* + * Obtain the status of a CMS message's signature. A CMS message can + * be signed my multiple signers; this function returns the status + * associated with signer 'n' as indicated by the signerIndex parameter. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + * + * Note that signature and certificate verification of a decoded message + * does *not* occur until this routine is called. + * + * All returned values are optional - pass NULL if you don't need a + * particular parameter. + * + * Note that errors like "bad signature" and "bad cert" do NOT cause this + * routine to return a nonzero error status itself; such errors are reported + * in the various out parameters, listed below. + * + * Inputs: + * ------- + * cmsDecoder : a CMSDecoder which has successfully performed a + * CMSDecoderFinalizeMessage(). + * signerIndex : indicates which of 'n' signers is being examined. + * Range is 0...(numSigners-1). + * policyOrArray : Either a SecPolicyRef or a CFArray of them. + * These policies are used to verify the signer's certificate. + * evaluateSecTrust : When TRUE, causes the SecTrust oebject created for the + * evaluation of the signer cert to actually be evaluated + * via SecTrustEvaluate(). When FALSE, the caller performs + * the SecTrustEvaluate() operation on the SecTrust object + * returned via the secTrust out parameter. + * NOTE: it is hazardous and not recommended to pass in FALSE + * for the evaluateSecTrust parameter as well as NULL for the + * secTrust out parameter, since no evaluation of the signer + * cert can occur in that situation. + * + * Outputs: + * -------- + * signerStatusOut -- An enum indicating the overall status. + * kCMSSignerUnsigned : message was not signed. + * kCMSSignerValid : both signature and signer certificate verified OK. + * kCMSSignerNeedsDetachedContent : a call to CMSDecoderSetDetachedContent() + * is required to ascertain the signature status. + * kCMSSignerInvalidSignature : bad signature. + * kCMSSignerInvalidCert : an error occurred verifying the signer's certificate. + * Further information available via the secTrust and + * certVerifyResultCode parameters. This will never be + * returned if evaluateSecTrust is FALSE. + * kCMSSignerInvalidIndex : specified signerIndex is larger than the number of + * signers (minus 1). + * + * secTrustOut -- The SecTrust object used to verify the signer's + * certificate. Caller must CFRelease this. + * certVerifyResultCodeOut -- The result of the certificate verification. If + * the evaluateSecTrust argument is set to FALSE on + * input, this out parameter is undefined on return. + * + * The certVerifyResultCode value can indicate a large number of errors; some of + * the most common and interesting errors are: + * + * CSSMERR_TP_INVALID_ANCHOR_CERT : The cert was verified back to a + * self-signed (root) cert which was present in the message, but + * that root cert is not a known, trusted root cert. + * CSSMERR_TP_NOT_TRUSTED: The cert could not be verified back to + * a root cert. + * CSSMERR_TP_VERIFICATION_FAILURE: A root cert was found which does + * not self-verify. + * CSSMERR_TP_VERIFY_ACTION_FAILED: Indicates a failure of the requested + * policy action. + * CSSMERR_TP_INVALID_CERTIFICATE: Indicates a bad leaf cert. + * CSSMERR_TP_CERT_EXPIRED: A cert in the chain was expired at the time of + * verification. + * CSSMERR_TP_CERT_NOT_VALID_YET: A cert in the chain was not yet valie at + * the time of verification. + */ +OSStatus CMSDecoderCopySignerStatus( + CMSDecoderRef cmsDecoder, + size_t signerIndex, + CFTypeRef policyOrArray, + Boolean evaluateSecTrust, + CMSSignerStatus * __nullable signerStatusOut, /* optional; RETURNED */ + SecTrustRef * __nullable CF_RETURNS_RETAINED secTrustOut, /* optional; RETURNED */ + OSStatus * __nullable certVerifyResultCodeOut) /* optional; RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_11_0); + +/* + * Obtain the email address of signer 'signerIndex' of a CMS message, if + * present. + * + * Returns errSecParam if the CMS message was not signed or if signerIndex + * is greater than the number of signers of the message minus one. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopySignerEmailAddress( + CMSDecoderRef cmsDecoder, + size_t signerIndex, + CFStringRef * __nonnull CF_RETURNS_RETAINED signerEmailAddressOut) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_11_0); + +/* + * Obtain the certificate of signer 'signerIndex' of a CMS message, if + * present. + * + * Returns errSecParam if the CMS message was not signed or if signerIndex + * is greater than the number of signers of the message minus one. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopySignerCert( + CMSDecoderRef cmsDecoder, + size_t signerIndex, + SecCertificateRef * __nonnull CF_RETURNS_RETAINED signerCertOut) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_11_0); + +/* + * Determine whether a CMS message was encrypted. Returns TRUE if so, FALSE if not. + * Note that if the message was encrypted, and the decoding succeeded, (i.e., + * CMSDecoderFinalizeMessage() returned errSecSuccess), then the message was successfully + * decrypted. + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderIsContentEncrypted( + CMSDecoderRef cmsDecoder, + Boolean *isEncryptedOut) + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_11_0); + +/* + * Obtain the eContentType OID for a SignedData's EncapsulatedContentType, if + * present. If the message was not signed this will return NULL. + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + * The returned OID's data is in the same format as a CSSM_OID; i.e., it's + * the encoded content of the OID, not including the tag and length bytes. + */ +OSStatus CMSDecoderCopyEncapsulatedContentType( + CMSDecoderRef cmsDecoder, + CFDataRef * __nonnull CF_RETURNS_RETAINED eContentTypeOut) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_11_0); + +/* + * Obtain an array of all of the certificates in a message. Elements of the + * returned array are SecCertificateRefs. The caller must CFRelease the returned + * array. If a message does not contain any certificates (which is the case for + * a message which is encrypted but not signed), the returned *certs value + * is NULL. The function will return errSecSuccess in this case. + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopyAllCerts( + CMSDecoderRef cmsDecoder, + CFArrayRef * __nonnull CF_RETURNS_RETAINED certsOut) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_11_0); + +/* + * Obtain the actual message content (payload), if any. If the message was + * signed with detached content this will return NULL. + * Caller must CFRelease the result. + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopyContent( + CMSDecoderRef cmsDecoder, + CFDataRef * __nonnull CF_RETURNS_RETAINED contentOut) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_11_0); + +/* + * Obtain the signing time of signer 'signerIndex' of a CMS message, if + * present. This is an unauthenticate time, although it is part of the + * signed attributes of the message. + * + * Returns errSecParam if the CMS message was not signed or if signerIndex + * is greater than the number of signers of the message minus one. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopySignerSigningTime( + CMSDecoderRef cmsDecoder, + size_t signerIndex, + CFAbsoluteTime *signingTime) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_11_0); + +#if TIMESTAMPING_SUPPORTED +/* + * Obtain the timestamp of signer 'signerIndex' of a CMS message, if + * present. This timestamp is an authenticated timestamp provided by + * a timestamping authority. + * + * Returns errSecParam if the CMS message was not signed or if signerIndex + * is greater than the number of signers of the message minus one. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopySignerTimestamp( + CMSDecoderRef cmsDecoder, + size_t signerIndex, + CFAbsoluteTime *timestamp) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_NA); + +/* + * Obtain the timestamp of signer 'signerIndex' of a CMS message, if + * present. This timestamp is an authenticated timestamp provided by + * a timestamping authority. Use the policy provided as a parameter + * + * Returns errSecParam if the CMS message was not signed or if signerIndex + * is greater than the number of signers of the message minus one. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopySignerTimestampWithPolicy( + CMSDecoderRef cmsDecoder, + CFTypeRef __nullable timeStampPolicy, + size_t signerIndex, /* usually 0 */ + CFAbsoluteTime *timestamp) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_NA); + +/* + * Obtain an array of the certificates in a timestamp response. Elements of the + * returned array are SecCertificateRefs. The caller must CFRelease the returned + * array. This timestamp is an authenticated timestamp provided by + * a timestamping authority. + * + * Returns errSecParam if the CMS message was not signed or if signerIndex + * is greater than the number of signers of the message minus one. It returns + * errSecItemNotFound if no certificates were found. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopySignerTimestampCertificates( + CMSDecoderRef cmsDecoder, + size_t signerIndex, /* usually 0 */ + CFArrayRef * __nonnull CF_RETURNS_RETAINED certificateRefs) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_NA); +#endif + +/* + * Obtain the SecCmsMessageRef associated with a CMSDecoderRef. Intended + * to be called after decoding the message (i.e., after + * CMSDecoderFinalizeMessage() to gain finer access to the contents of the + * SecCmsMessageRef than is otherwise available via the CMSDecoder interface. + * Returns a NULL SecCmsMessageRef if CMSDecoderFinalizeMessage() has not been + * called. + * + * The CMSDecoder retains ownership of the returned SecCmsMessageRef. + */ +OSStatus CMSDecoderGetCmsMessage( + CMSDecoderRef cmsDecoder, + SecCmsMessageRef _Nullable * _Nonnull cmsMessage); /* RETURNED */ + + +/* + * Optionally specify a SecCmsDecoderRef to use with a CMSDecoderRef. + * If this is called, it must be called before the first call to + * CMSDecoderUpdateMessage(). The CMSDecoderRef takes ownership of the + * incoming SecCmsDecoderRef. + */ +OSStatus CMSDecoderSetDecoder( + CMSDecoderRef cmsDecoder, + SecCmsDecoderRef decoder); + +/* + * Obtain the SecCmsDecoderRef associated with a CMSDecoderRef. + * Returns a NULL SecCmsDecoderRef if neither CMSDecoderSetDecoder() nor + * CMSDecoderUpdateMessage() has been called. + * The CMSDecoderRef retains ownership of the SecCmsDecoderRef. + */ +OSStatus CMSDecoderGetDecoder( + CMSDecoderRef cmsDecoder, + SecCmsDecoderRef _Nullable * _Nonnull decoder); /* RETURNED */ + +/* + * Obtain the Hash Agility attribute value of signer 'signerIndex' + * of a CMS message, if present. + * + * Returns errSecParam if the CMS message was not signed or if signerIndex + * is greater than the number of signers of the message minus one. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopySignerAppleCodesigningHashAgility( + CMSDecoderRef cmsDecoder, + size_t signerIndex, /* usually 0 */ + CFDataRef CF_RETURNS_RETAINED * _Nonnull hashAgilityAttrValue); /* RETURNED */ + + +CF_ASSUME_NONNULL_END + +__END_DECLS + +#endif /* _CMS_DECODER_H_ */ +