MYDecoder.h
author Jens Alfke <jens@mooseyard.com>
Wed Jun 10 09:02:18 2009 -0700 (2009-06-10)
changeset 25 38c3c3923e1f
parent 8 4c0eafa7b233
permissions -rw-r--r--
Changed the X.509 version number in generated certs from 1 to 3, so that SecCertificateCreateFromData on iPhone will accept them. :-/
     1 //
     2 //  CryptoDecoder.h
     3 //  Cloudy
     4 //
     5 //  Created by Jens Alfke on 1/16/08.
     6 //  Copyright 2008 Jens Alfke. All rights reserved.
     7 //
     8 
     9 #import <Cocoa/Cocoa.h>
    10 #import <Security/CMSDecoder.h>
    11 
    12 @class MYKeychain, MYCertificate;
    13 
    14 
    15 /** Decodes a CMS-formatted message into the original data, and identifies & verifies signatures. */
    16 @interface MYDecoder : NSObject 
    17 {
    18     @private
    19     CMSDecoderRef _decoder;
    20     OSStatus _error;
    21     SecPolicyRef _policy;
    22 }
    23 
    24 /** Initializes a new decoder. */
    25 - (id) init;
    26 
    27 /** Initializes a new decoder and reads the entire message data. */
    28 - (id) initWithData: (NSData*)data error: (NSError**)outError;
    29 
    30 /** Specifies a keychain to use to look up certificates and keys, instead of the default
    31     keychain search path. */
    32 - (BOOL) useKeychain: (MYKeychain*)keychain;
    33 
    34 /** Adds data to the decoder. You can add the entire data at once, or in bits and pieces
    35     (if you're reading it from a stream). */
    36 - (BOOL) addData: (NSData*)data;
    37 
    38 /** The error, if any, that occurred while decoding the content.
    39     If -addData: returns NO, read this property to find out what went wrong.
    40     The most likely error is (NSOSStatusErrorDomain, errSecUnknownFormat). */
    41 @property (readonly) NSError *error;
    42 
    43 /** If the message content is detached (stored separately from the encoded message),
    44     you must copy it to this property before calling -finish, so that the decoder can use it
    45     to verify signatures. */
    46 @property (retain) NSData *detachedContent;
    47 
    48 /** Tells the decoder that all of the data has been read, after the last call to -addData:. 
    49     You must call this before accessing the message content or metadata. */
    50 - (BOOL) finish;
    51 
    52 /** The decoded message content. */
    53 @property (readonly) NSData* content;
    54 
    55 /** YES if the message was signed. (Use the signers property to see who signed it.) */
    56 @property (readonly) BOOL isSigned;
    57 
    58 /** YES if the message was encrypted. */
    59 @property (readonly) BOOL isEncrypted;
    60 
    61 /** An array of MYSigner objects representing the identities who signed the message.
    62     Nil if the message is unsigned. */
    63 @property (readonly) NSArray* signers;
    64  
    65 /** All of the certificates (as MYCertificate objects) that were attached to the message. */
    66 @property (readonly) NSArray* certificates;
    67 
    68 
    69 /** @name Expert
    70  *  Advanced methods. 
    71  */
    72 //@{
    73 
    74 /** The X.509 content-type of the message contents.
    75     The Data field points to autoreleased memory: do not free it yourself, and do not
    76     expect it to remain valid after the calling method returns. */
    77 @property (readonly) CSSM_OID contentType;
    78 
    79 /** The Policy that will be used to evaluate trust when calling MYSigner.copyTrust.
    80     NULL by default. */
    81 @property (assign) SecPolicyRef policy;
    82 
    83 /** Returns a string with detailed information about the message metadata.
    84     Not user-presentable; used for debugging. */
    85 - (NSString*) dump;
    86 
    87 //@}
    88 
    89 @end
    90 
    91 
    92 /** Represents a signer of a CMS message, as returned by the MYDecoder.signers property. */
    93 @interface MYSigner : NSObject
    94 {
    95     @private
    96     CMSDecoderRef _decoder;
    97     size_t _index;
    98     CFTypeRef _policy;
    99     CMSSignerStatus _status;
   100     OSStatus _verifyResult;
   101     SecTrustRef _trust;
   102 }
   103 
   104 /** The status of the signature, i.e. whether it's valid or not.
   105  *  Values include:
   106  *	  kCMSSignerValid               :both signature and signer certificate verified OK.
   107  *	  kCMSSignerNeedsDetachedContent:the MYDecoder's detachedContent property must be set,
   108  *                                   to ascertain the signature status.
   109  *	  kCMSSignerInvalidSignature    :bad signature -- either the content or the signature
   110  *                                   data were tampered with after the message was encoded.
   111  *	  kCMSSignerInvalidCert         :an error occurred verifying the signer's certificate.
   112  *							         Further information available via the verifyResult
   113  *                                   and copyTrust methods.
   114  */
   115 @property (readonly) CMSSignerStatus status;
   116 
   117 /** The signer's certificate.
   118     You should check the status property first, to see whether the signature and certificate
   119     are valid.
   120     For safety purposes, if you haven't checked status yet, this method will return nil
   121     if the signer status is not kCMSSignerValid. */
   122 @property (readonly) MYCertificate *certificate;
   123 
   124 /** The signer's email address (if any), as stored in the certificate. */
   125 @property (readonly) NSString* emailAddress;
   126 
   127 /** @name Expert
   128  *  Advanced methods. 
   129  */
   130 //@{
   131 
   132 /** Returns the SecTrustRef that was used to verify the certificate.
   133     You can use this object to get more detailed information about how the verification was done.
   134     If you set the parent decoder's policy property, then that SecPolicy will be used to evaluate
   135     trust; otherwise you'll need to do it yourself using the SecTrust object. */
   136 @property (readonly) SecTrustRef trust;
   137 
   138 /** The result of certificate verification, as a CSSM_RESULT code; 
   139  *  a nonzero value indicates an error.
   140  *
   141  * Some of the most common and interesting errors are:
   142  *
   143  * CSSMERR_TP_INVALID_ANCHOR_CERT : The cert was verified back to a 
   144  *		self-signed (root) cert which was present in the message, but 
   145  *		that root cert is not a known, trusted root cert. 
   146  * CSSMERR_TP_NOT_TRUSTED: The cert could not be verified back to 
   147  *		a root cert.
   148  * CSSMERR_TP_VERIFICATION_FAILURE: A root cert was found which does
   149  *   	not self-verify. 
   150  * CSSMERR_TP_VERIFY_ACTION_FAILED: Indicates a failure of the requested 
   151  *		policy action. 
   152  * CSSMERR_TP_INVALID_CERTIFICATE: Indicates a bad leaf cert. 
   153  * CSSMERR_TP_CERT_EXPIRED: A cert in the chain was expired at the time of
   154  *		verification.
   155  * CSSMERR_TP_CERT_NOT_VALID_YET: A cert in the chain was not yet valie at 
   156  *		the time of	verification.
   157  */
   158 @property (readonly) OSStatus verifyResult;
   159 
   160 //@}
   161 
   162 @end
   163 
   164 
   165 enum {
   166     /** Returned from MYSigner.status to indicate a failure (non-noErr return value)
   167      of the underlying CMSDecoderCopySignerStatus call. Should never occur. */
   168     kMYSignerStatusCheckFailed = 666
   169 };