/ CMS / CMSDecoder.h
CMSDecoder.h
  1  /*
  2   * Copyright (c) 2006-2018 Apple Inc. All Rights Reserved.
  3   *
  4   * @APPLE_LICENSE_HEADER_START@
  5   *
  6   * This file contains Original Code and/or Modifications of Original Code
  7   * as defined in and that are subject to the Apple Public Source License
  8   * Version 2.0 (the 'License'). You may not use this file except in
  9   * compliance with the License. Please obtain a copy of the License at
 10   * http://www.opensource.apple.com/apsl/ and read it before using this
 11   * file.
 12   *
 13   * The Original Code and all software distributed under the License are
 14   * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 15   * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 16   * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 17   * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 18   * Please see the License for the specific language governing rights and
 19   * limitations under the License.
 20   *
 21   * @APPLE_LICENSE_HEADER_END@
 22   */
 23  
 24  /*
 25   * CMSDecoder.h - decode, decrypt, and/or verify signatures of messages in the
 26   *				  Cryptographic Message Syntax (CMS), per RFC 3852.
 27   *
 28   * See CMSEncoder.h for general information about CMS messages.
 29   */
 30  
 31  #ifndef _CMS_DECODER_H_
 32  #define _CMS_DECODER_H_
 33  
 34  #include <CoreFoundation/CoreFoundation.h>
 35  #include <Security/SecCertificate.h>
 36  #include <Security/SecTrust.h>
 37  #include <AvailabilityMacros.h>
 38  #include <stdint.h>
 39  
 40  __BEGIN_DECLS
 41  
 42  CF_ASSUME_NONNULL_BEGIN
 43  
 44  /*
 45   * Opaque reference to a CMS decoder object.
 46   * This is a CF object, with standard CF semantics; dispose of it
 47   * with CFRelease().
 48   */
 49  typedef struct CF_BRIDGED_TYPE(id) _CMSDecoder *CMSDecoderRef;
 50  
 51  CFTypeID CMSDecoderGetTypeID(void);
 52  
 53  /*
 54   * Status of signature and signer information in a signed message.
 55   */
 56  typedef CF_ENUM(uint32_t, CMSSignerStatus) {
 57      kCMSSignerUnsigned = 0,				/* message was not signed */
 58      kCMSSignerValid,					/* message was signed and signature verify OK */
 59      kCMSSignerNeedsDetachedContent,		/* message was signed but needs detached content
 60                                           *   to verify */
 61      kCMSSignerInvalidSignature,			/* message was signed but had a signature error */
 62      kCMSSignerInvalidCert,				/* message was signed but an error occurred in verifying
 63                                           *   the signer's certificate */
 64      kCMSSignerInvalidIndex				/* specified signer index out of range */
 65  };
 66  
 67  /*
 68   * Create a CMSDecoder. Result must eventually be freed via CFRelease().
 69   */
 70  OSStatus CMSDecoderCreate(CMSDecoderRef * __nonnull CF_RETURNS_RETAINED cmsDecoderOut)	/* RETURNED */
 71      __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0));
 72  
 73  /*
 74   * Feed raw bytes of the message to be decoded into the decoder. Can be called
 75   * multiple times.
 76   * Returns errSecUnknownFormat upon detection of improperly formatted CMS
 77   * message.
 78   */
 79  OSStatus CMSDecoderUpdateMessage(
 80      CMSDecoderRef		cmsDecoder,
 81      const void			*msgBytes,
 82      size_t				msgBytesLen)
 83      __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0));
 84  
 85  /*
 86   * Indicate that no more CMSDecoderUpdateMessage() calls are forthcoming;
 87   * finish decoding the message.
 88   * Returns errSecUnknownFormat upon detection of improperly formatted CMS
 89   * message.
 90   */
 91  OSStatus CMSDecoderFinalizeMessage(CMSDecoderRef cmsDecoder)
 92      __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0));
 93  
 94  /*
 95   * A signed CMS message optionally includes the data which was signed. If the
 96   * message does not include the signed data, caller specifies the signed data
 97   * (the "detached content") here.
 98   *
 99   * This can be called either before or after the actual decoding of the message
100   * (via CMSDecoderUpdateMessage() and CMSDecoderFinalizeMessage()); the only
101   * restriction is that, if detached content is required, this function must
102   * be called befoere successfully ascertaining the signature status via
103   * CMSDecoderCopySignerStatus().
104   */
105  OSStatus CMSDecoderSetDetachedContent(
106      CMSDecoderRef		cmsDecoder,
107      CFDataRef			detachedContent)
108      __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0));
109  
110  /*
111   * Obtain the detached content specified in CMSDecoderSetDetachedContent().
112   * Returns a NULL detachedContent if no detached content has been specified.
113   * Caller must CFRelease() the result.
114   */
115  OSStatus CMSDecoderCopyDetachedContent(
116      CMSDecoderRef		cmsDecoder,
117      CFDataRef * __nonnull CF_RETURNS_RETAINED detachedContentOut)	/* RETURNED */
118      __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0));
119  
120  #if SEC_OS_OSX
121  /*
122   * This function no longer affects the behavior of the CMS Decoder. Please
123   * discontinue use.
124   */
125  OSStatus CMSDecoderSetSearchKeychain(
126      CMSDecoderRef        cmsDecoder,
127      CFTypeRef            keychainOrArray)
128      API_DEPRECATED_WITH_REPLACEMENT("SecKeychainSetSearchList",macos(10.5, 10.13)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst);
129  #endif // SEC_OS_OSX
130  
131  /*
132   * Obtain the number of signers of a message. A result of zero indicates that
133   * the message was not signed.
134   * This cannot be called until after CMSDecoderFinalizeMessage() is called.
135   */
136  OSStatus CMSDecoderGetNumSigners(
137      CMSDecoderRef		cmsDecoder,
138      size_t				*numSignersOut)	/* RETURNED */
139      __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0));
140  
141  /*
142   * Obtain the status of a CMS message's signature. A CMS message can
143   * be signed my multiple signers; this function returns the status
144   * associated with signer 'n' as indicated by the signerIndex parameter.
145   *
146   * This cannot be called until after CMSDecoderFinalizeMessage() is called.
147   *
148   * Note that signature and certificate verification of a decoded message
149   * does *not* occur until this routine is called.
150   *
151   * All returned values are optional - pass NULL if you don't need a
152   * particular parameter.
153   *
154   * Note that errors like "bad signature" and "bad cert" do NOT cause this
155   * routine to return a nonzero error status itself; such errors are reported
156   * in the various out parameters, listed below.
157   *
158   * Inputs:
159   * -------
160   * cmsDecoder       : a CMSDecoder which has successfully performed a
161   *                    CMSDecoderFinalizeMessage().
162   * signerIndex      : indicates which of 'n' signers is being examined.
163   *                    Range is 0...(numSigners-1).
164   * policyOrArray    : Either a SecPolicyRef or a CFArray of them.
165   *                    These policies are used to verify the signer's certificate.
166   * evaluateSecTrust : When TRUE, causes the SecTrust oebject created for the
167   *                    evaluation of the signer cert to actually be evaluated
168   *                    via SecTrustEvaluate(). When FALSE, the caller performs
169   *                    the SecTrustEvaluate() operation on the SecTrust object
170   *                    returned via the secTrust out parameter.
171   *                    NOTE: it is hazardous and not recommended to pass in FALSE
172   *                    for the evaluateSecTrust parameter as well as NULL for the
173   *                    secTrust out parameter, since no evaluation of the signer
174   *                    cert can occur in that situation.
175   *
176   * Outputs:
177   * --------
178   *	signerStatusOut			-- An enum indicating the overall status.
179   *		kCMSSignerUnsigned         : message was not signed.
180   *		kCMSSignerValid            : both signature and signer certificate verified OK.
181   *		kCMSSignerNeedsDetachedContent : a call to CMSDecoderSetDetachedContent()
182   *							         is required to ascertain the signature status.
183   *		kCMSSignerInvalidSignature : bad signature.
184   *		kCMSSignerInvalidCert      : an error occurred verifying the signer's certificate.
185   *							         Further information available via the secTrust and
186   *							         certVerifyResultCode parameters. This will never be
187   *								     returned if evaluateSecTrust is FALSE.
188   *		kCMSSignerInvalidIndex     : specified signerIndex is larger than the number of
189   *								     signers (minus 1).
190   *
191   *	secTrustOut				-- The SecTrust object used to verify the signer's
192   *							   certificate. Caller must CFRelease this.
193   *	certVerifyResultCodeOut	-- The result of the certificate verification. If
194   *							   the evaluateSecTrust argument is set to FALSE on
195   *							   input, this out parameter is undefined on return.
196   *
197   * The certVerifyResultCode value can indicate a large number of errors; some of
198   * the most common and interesting errors are:
199   *
200   * CSSMERR_TP_INVALID_ANCHOR_CERT : The cert was verified back to a
201   *		self-signed (root) cert which was present in the message, but
202   *		that root cert is not a known, trusted root cert.
203   * CSSMERR_TP_NOT_TRUSTED: The cert could not be verified back to
204   *		a root cert.
205   * CSSMERR_TP_VERIFICATION_FAILURE: A root cert was found which does
206   *   	not self-verify.
207   * CSSMERR_TP_VERIFY_ACTION_FAILED: Indicates a failure of the requested
208   *		policy action.
209   * CSSMERR_TP_INVALID_CERTIFICATE: Indicates a bad leaf cert.
210   * CSSMERR_TP_CERT_EXPIRED: A cert in the chain was expired at the time of
211   *		verification.
212   * CSSMERR_TP_CERT_NOT_VALID_YET: A cert in the chain was not yet valie at
213   *		the time of	verification.
214   */
215  OSStatus CMSDecoderCopySignerStatus(
216      CMSDecoderRef               cmsDecoder,
217      size_t                      signerIndex,
218      CFTypeRef                   policyOrArray,
219      Boolean                     evaluateSecTrust,
220      CMSSignerStatus * __nullable signerStatusOut,               /* optional; RETURNED */
221      SecTrustRef * __nullable CF_RETURNS_RETAINED secTrustOut,   /* optional; RETURNED */
222      OSStatus * __nullable certVerifyResultCodeOut)              /* optional; RETURNED */
223      __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0));
224  
225  /*
226   * Obtain the email address of signer 'signerIndex' of a CMS message, if
227   * present.
228   *
229   * Returns errSecParam if the CMS message was not signed or if signerIndex
230   * is greater than the number of signers of the message minus one.
231   *
232   * This cannot be called until after CMSDecoderFinalizeMessage() is called.
233   */
234  OSStatus CMSDecoderCopySignerEmailAddress(
235      CMSDecoderRef		cmsDecoder,
236      size_t				signerIndex,
237      CFStringRef	* __nonnull CF_RETURNS_RETAINED signerEmailAddressOut)	/* RETURNED */
238      __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0));
239  
240  /*
241   * Obtain the certificate of signer 'signerIndex' of a CMS message, if
242   * present.
243   *
244   * Returns errSecParam if the CMS message was not signed or if signerIndex
245   * is greater than the number of signers of the message minus one.
246   *
247   * This cannot be called until after CMSDecoderFinalizeMessage() is called.
248   */
249  OSStatus CMSDecoderCopySignerCert(
250      CMSDecoderRef		cmsDecoder,
251      size_t				signerIndex,
252      SecCertificateRef * __nonnull CF_RETURNS_RETAINED signerCertOut)    /* RETURNED */
253      __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0));
254  
255  /*
256   * Determine whether a CMS message was encrypted. Returns TRUE if so, FALSE if not.
257   * Note that if the message was encrypted, and the decoding succeeded, (i.e.,
258   * CMSDecoderFinalizeMessage() returned errSecSuccess), then the message was successfully
259   * decrypted.
260   * This cannot be called until after CMSDecoderFinalizeMessage() is called.
261   */
262  OSStatus CMSDecoderIsContentEncrypted(
263      CMSDecoderRef		cmsDecoder,
264      Boolean				*isEncryptedOut)
265      __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0));
266  
267  /*
268   * Obtain the eContentType OID for a SignedData's EncapsulatedContentType, if
269   * present. If the message was not signed this will return NULL.
270   * This cannot be called until after CMSDecoderFinalizeMessage() is called.
271   * The returned OID's data is in the same format as a CSSM_OID; i.e., it's
272   * the encoded content of the OID, not including the tag and length bytes.
273   */
274  OSStatus CMSDecoderCopyEncapsulatedContentType(
275     CMSDecoderRef		cmsDecoder,
276     CFDataRef * __nonnull CF_RETURNS_RETAINED eContentTypeOut)  /* RETURNED */
277      __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0));
278  
279  /*
280   * Obtain an array of all of the certificates in a message. Elements of the
281   * returned array are SecCertificateRefs. The caller must CFRelease the returned
282   * array. If a message does not contain any certificates (which is the case for
283   * a message which is encrypted but not signed), the returned *certs value
284   * is NULL. The function will return errSecSuccess in this case.
285   * This cannot be called until after CMSDecoderFinalizeMessage() is called.
286   */
287  OSStatus CMSDecoderCopyAllCerts(
288      CMSDecoderRef		cmsDecoder,
289      CFArrayRef * __nonnull CF_RETURNS_RETAINED certsOut)    /* RETURNED */
290      __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0));
291  
292  /*
293   * Obtain the actual message content (payload), if any. If the message was
294   * signed with detached content this will return NULL.
295   * Caller must CFRelease the result.
296   * This cannot be called until after CMSDecoderFinalizeMessage() is called.
297   */
298  OSStatus CMSDecoderCopyContent(
299      CMSDecoderRef		cmsDecoder,
300      CFDataRef * __nonnull CF_RETURNS_RETAINED contentOut)	/* RETURNED */
301      __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0));
302  
303  /*
304   * Obtain the signing time of signer 'signerIndex' of a CMS message, if
305   * present. This is an unauthenticate time, although it is part of the
306   * signed attributes of the message.
307   *
308   * Returns errSecParam if the CMS message was not signed or if signerIndex
309   * is greater than the number of signers of the message minus one.
310   *
311   * This cannot be called until after CMSDecoderFinalizeMessage() is called.
312   */
313  OSStatus CMSDecoderCopySignerSigningTime(
314      CMSDecoderRef		cmsDecoder,
315      size_t				signerIndex,
316      CFAbsoluteTime      *signingTime)			/* RETURNED */
317      __API_AVAILABLE(macos(10.8)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0));
318  
319  /*
320   * Obtain the timestamp of signer 'signerIndex' of a CMS message, if
321   * present. This timestamp is an authenticated timestamp provided by
322   * a timestamping authority.
323   *
324   * Returns errSecParam if the CMS message was not signed or if signerIndex
325   * is greater than the number of signers of the message minus one.
326   *
327   * This cannot be called until after CMSDecoderFinalizeMessage() is called.
328   */
329  OSStatus CMSDecoderCopySignerTimestamp(
330      CMSDecoderRef		cmsDecoder,
331      size_t				signerIndex,
332      CFAbsoluteTime      *timestamp)			/* RETURNED */
333      API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst);
334  
335  /*
336   * Obtain the timestamp of signer 'signerIndex' of a CMS message, if
337   * present. This timestamp is an authenticated timestamp provided by
338   * a timestamping authority. Use the policy provided as a parameter
339   *
340   * Returns errSecParam if the CMS message was not signed or if signerIndex
341   * is greater than the number of signers of the message minus one.
342   *
343   * This cannot be called until after CMSDecoderFinalizeMessage() is called.
344   */
345  OSStatus CMSDecoderCopySignerTimestampWithPolicy(
346      CMSDecoderRef		cmsDecoder,
347      CFTypeRef __nullable timeStampPolicy,
348      size_t				signerIndex,        /* usually 0 */
349      CFAbsoluteTime      *timestamp)			/* RETURNED */
350      API_AVAILABLE(macos(10.10)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst);
351  
352  /*
353   * Obtain an array of the certificates in a timestamp response. Elements of the
354   * returned array are SecCertificateRefs. The caller must CFRelease the returned
355   * array. This timestamp is an authenticated timestamp provided by
356   * a timestamping authority.
357   *
358   * Returns errSecParam if the CMS message was not signed or if signerIndex
359   * is greater than the number of signers of the message minus one. It returns
360   * errSecItemNotFound if no certificates were found.
361   *
362   * This cannot be called until after CMSDecoderFinalizeMessage() is called.
363   */
364  OSStatus CMSDecoderCopySignerTimestampCertificates(
365      CMSDecoderRef		cmsDecoder,
366      size_t				signerIndex,                            /* usually 0 */
367      CFArrayRef * __nonnull CF_RETURNS_RETAINED certificateRefs) /* RETURNED */
368      API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst);
369  
370  CF_ASSUME_NONNULL_END
371  
372  __END_DECLS
373  
374  #endif	/* _CMS_DECODER_H_ */
375