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