MYDecoder.h
changeset 8 4c0eafa7b233
child 9 aa5eb3fd6ebf
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/MYDecoder.h	Sun Apr 12 22:02:20 2009 -0700
     1.3 @@ -0,0 +1,170 @@
     1.4 +//
     1.5 +//  CryptoDecoder.h
     1.6 +//  Cloudy
     1.7 +//
     1.8 +//  Created by Jens Alfke on 1/16/08.
     1.9 +//  Copyright 2008 Jens Alfke. All rights reserved.
    1.10 +//
    1.11 +
    1.12 +#import <Cocoa/Cocoa.h>
    1.13 +#import <Security/CMSDecoder.h>
    1.14 +
    1.15 +@class MYKeychain, MYCertificate;
    1.16 +
    1.17 +
    1.18 +/** Decodes a CMS-formatted message into the original data, and identifies & verifies signatures. */
    1.19 +@interface MYDecoder : NSObject 
    1.20 +{
    1.21 +    @private
    1.22 +    CMSDecoderRef _decoder;
    1.23 +    OSStatus _error;
    1.24 +    SecPolicyRef _policy;
    1.25 +}
    1.26 +
    1.27 +/** Initializes a new decoder. */
    1.28 +- (id) init;
    1.29 +
    1.30 +/** Initializes a new decoder and reads the entire message data. */
    1.31 +- (id) initWithData: (NSData*)data error: (NSError**)outError;
    1.32 +
    1.33 +/** Specifies a keychain to use to look up certificates and keys, instead of the default
    1.34 +    keychain search path. */
    1.35 +- (BOOL) useKeychain: (MYKeychain*)keychain;
    1.36 +
    1.37 +/** Adds data to the decoder. You can add the entire data at once, or in bits and pieces
    1.38 +    (if you're reading it from a stream). */
    1.39 +- (BOOL) addData: (NSData*)data;
    1.40 +
    1.41 +/** The error, if any, that occurred while decoding the content.
    1.42 +    If -addData: returns NO, read this property to find out what went wrong.
    1.43 +    The most likely error is (NSOSStatusErrorDomain, errSecUnknownFormat). */
    1.44 +@property (readonly) NSError *error;
    1.45 +
    1.46 +/** If the message content is detached (stored separately from the encoded message),
    1.47 +    you must copy it to this property before calling -finish, so that the decoder can use it
    1.48 +    to verify signatures. */
    1.49 +@property (retain) NSData *detachedContent;
    1.50 +
    1.51 +/** Tells the decoder that all of the data has been read, after the last call to -addData:. 
    1.52 +    You must call this before accessing the message content or metadata. */
    1.53 +- (BOOL) finish;
    1.54 +
    1.55 +/** The decoded message content. */
    1.56 +@property (readonly) NSData* content;
    1.57 +
    1.58 +/** YES if the message was signed. (Use the signers property to see who signed it.) */
    1.59 +@property (readonly) BOOL isSigned;
    1.60 +
    1.61 +/** YES if the message was encrypted. */
    1.62 +@property (readonly) BOOL isEncrypted;
    1.63 +
    1.64 +/** An array of MYSigner objects representing the identities who signed the message.
    1.65 +    Nil if the message is unsigned. */
    1.66 +@property (readonly) NSArray* signers;
    1.67 + 
    1.68 +/** All of the certificates (as MYCertificate objects) that were attached to the message. */
    1.69 +@property (readonly) NSArray* certificates;
    1.70 +
    1.71 +
    1.72 +/** @name Expert
    1.73 + *  Advanced methods. 
    1.74 + */
    1.75 +//@{
    1.76 +
    1.77 +/** The X.509 content-type of the message contents.
    1.78 +    The Data field points to autoreleased memory: do not free it yourself, and do not
    1.79 +    expect it to remain valid after the calling method returns. */
    1.80 +@property (readonly) CSSM_OID contentType;
    1.81 +
    1.82 +/** The Policy that will be used to evaluate trust when calling MYSigner.copyTrust.
    1.83 +    NULL by default. */
    1.84 +@property (assign) SecPolicyRef policy;
    1.85 +
    1.86 +/** Returns a string with detailed information about the message metadata.
    1.87 +    Not user-presentable; used for debugging. */
    1.88 +- (NSString*) dump;
    1.89 +
    1.90 +//@}
    1.91 +
    1.92 +@end
    1.93 +
    1.94 +
    1.95 +/** Represents a signer of a CMS message, as returned by the MYDecoder.signers property. */
    1.96 +@interface MYSigner : NSObject
    1.97 +{
    1.98 +    @private
    1.99 +    CMSDecoderRef _decoder;
   1.100 +    size_t _index;
   1.101 +    CFTypeRef _policy;
   1.102 +    CMSSignerStatus _status;
   1.103 +    OSStatus _verifyResult;
   1.104 +    SecTrustRef _trust;
   1.105 +}
   1.106 +
   1.107 +/** The status of the signature, i.e. whether it's valid or not.
   1.108 + *  Values include:
   1.109 + *	  kCMSSignerValid               :both signature and signer certificate verified OK.
   1.110 + *	  kCMSSignerNeedsDetachedContent:the MYDecoder's detachedContent property must be set,
   1.111 + *                                   to ascertain the signature status.
   1.112 + *	  kCMSSignerInvalidSignature    :bad signature -- either the content or the signature
   1.113 + *                                   data were tampered with after the message was encoded.
   1.114 + *	  kCMSSignerInvalidCert         :an error occurred verifying the signer's certificate.
   1.115 + *							         Further information available via the verifyResult
   1.116 + *                                   and copyTrust methods.
   1.117 + */
   1.118 +@property (readonly) CMSSignerStatus status;
   1.119 +
   1.120 +/** The signer's certificate.
   1.121 +    You should check the status property first, to see whether the signature and certificate
   1.122 +    are valid.
   1.123 +    For safety purposes, if you haven't checked status yet, this method will return nil
   1.124 +    if the signer status is not kCMSSignerValid. */
   1.125 +@property (readonly) MYCertificate *certificate;
   1.126 +
   1.127 +/** The signer's email address (if any), as stored in the certificate. */
   1.128 +@property (readonly) NSString* emailAddress;
   1.129 +
   1.130 +/** @name Expert
   1.131 + *  Advanced methods. 
   1.132 + */
   1.133 +//@{
   1.134 +
   1.135 +/** Returns the SecTrustRef that was used to verify the certificate.
   1.136 +    You can use this object to get more detailed information about how the verification was done.
   1.137 +    If you set the parent decoder's policy property, then that SecPolicy will be used to evaluate
   1.138 +    trust; otherwise you'll need to do it yourself using the SecTrust object.
   1.139 +    You must CFRelease the result when you're finished with it. */
   1.140 +- (SecTrustRef) trust;
   1.141 +
   1.142 +/** The result of certificate verification, as a CSSM_RESULT code; 
   1.143 + *  a nonzero value indicates an error.
   1.144 + *
   1.145 + * Some of the most common and interesting errors are:
   1.146 + *
   1.147 + * CSSMERR_TP_INVALID_ANCHOR_CERT : The cert was verified back to a 
   1.148 + *		self-signed (root) cert which was present in the message, but 
   1.149 + *		that root cert is not a known, trusted root cert. 
   1.150 + * CSSMERR_TP_NOT_TRUSTED: The cert could not be verified back to 
   1.151 + *		a root cert.
   1.152 + * CSSMERR_TP_VERIFICATION_FAILURE: A root cert was found which does
   1.153 + *   	not self-verify. 
   1.154 + * CSSMERR_TP_VERIFY_ACTION_FAILED: Indicates a failure of the requested 
   1.155 + *		policy action. 
   1.156 + * CSSMERR_TP_INVALID_CERTIFICATE: Indicates a bad leaf cert. 
   1.157 + * CSSMERR_TP_CERT_EXPIRED: A cert in the chain was expired at the time of
   1.158 + *		verification.
   1.159 + * CSSMERR_TP_CERT_NOT_VALID_YET: A cert in the chain was not yet valie at 
   1.160 + *		the time of	verification.
   1.161 + */
   1.162 +@property (readonly) OSStatus verifyResult;
   1.163 +
   1.164 +//@}
   1.165 +
   1.166 +@end
   1.167 +
   1.168 +
   1.169 +enum {
   1.170 +    /** Returned from MYSigner.status to indicate a failure (non-noErr return value)
   1.171 +     of the underlying CMSDecoderCopySignerStatus call. Should never occur. */
   1.172 +    kMYSignerStatusCheckFailed = 666
   1.173 +};