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