MYEncoder.m
author snej@snej.local
Sun Apr 12 22:16:14 2009 -0700 (2009-04-12)
changeset 9 aa5eb3fd6ebf
child 14 3af1d1c0ceb5
permissions -rw-r--r--
Doc touch-up
     1 //
     2 //  MYEncoder.m
     3 //  MYCrypto
     4 //
     5 //  Created by Jens Alfke on 1/16/08.
     6 //  Copyright 2008-2009 Jens Alfke. All rights reserved.
     7 //
     8 
     9 #import "MYEncoder.h"
    10 #import "MYIdentity.h"
    11 #import "MYCrypto_Private.h"
    12 #import "Test.h"
    13 #import "MYErrorUtils.h"
    14 
    15 
    16 @implementation MYEncoder
    17 
    18 
    19 - (id) init
    20 {
    21     self = [super init];
    22     if (self != nil) {
    23         if( ! checksave(CMSEncoderCreate(&_encoder)) ) {
    24             [self release];
    25             return nil;
    26         }
    27     }
    28     return self;
    29 }
    30 
    31 - (void) dealloc
    32 {
    33     if(_encoder) CFRelease(_encoder);
    34     [super dealloc];
    35 }
    36 
    37 
    38 
    39 - (BOOL) addSigner: (MYIdentity*)signer
    40 {
    41     Assert(signer);
    42     return checksave( CMSEncoderAddSigners(_encoder, signer.identityRef) );
    43 }
    44 
    45 - (BOOL) addRecipient: (MYCertificate*)recipient
    46 {
    47     Assert(recipient);
    48     return checksave( CMSEncoderAddRecipients(_encoder, recipient.certificateRef) );
    49 }
    50 
    51 - (BOOL) addSupportingCert: (MYCertificate*)supportingCert
    52 {
    53     Assert(supportingCert);
    54     return checksave( CMSEncoderAddSupportingCerts(_encoder, supportingCert.certificateRef) );
    55 }
    56 
    57 - (BOOL) addTimestamp
    58 {
    59     return checksave( CMSEncoderAddSignedAttributes(_encoder, kCMSAttrSigningTime) );
    60 }
    61 
    62 
    63 - (NSError*) error
    64 {
    65     if( _error )
    66         return MYError(_error, NSOSStatusErrorDomain, 
    67                        @"%@", MYErrorName(NSOSStatusErrorDomain,_error));
    68     else
    69         return nil;
    70 }
    71 
    72 
    73 - (CMSCertificateChainMode) certificateChainMode
    74 {
    75     CMSCertificateChainMode mode;
    76     if( CMSEncoderGetCertificateChainMode(_encoder, &mode) == noErr )
    77         return mode;
    78     else
    79         return -1;
    80 }
    81 
    82 - (void) setCertificateChainMode: (CMSCertificateChainMode)mode
    83 {
    84     checksave( CMSEncoderSetCertificateChainMode(_encoder, mode) );
    85 }
    86 
    87 - (BOOL) hasDetachedContent
    88 {
    89     Boolean detached;
    90     return CMSEncoderGetHasDetachedContent(_encoder, &detached)==noErr && detached;
    91 }
    92 
    93 - (void) setHasDetachedContent: (BOOL)detached
    94 {
    95     checksave( CMSEncoderSetHasDetachedContent(_encoder, detached) );
    96 }
    97 
    98 - (NSData*) _dataFromFunction: (OSStatus (*)(CMSEncoderRef,CFDataRef*))function
    99 {
   100     CFDataRef data=NULL;
   101     if( checksave( (*function)(_encoder, &data) ) )
   102         return [(NSData*)CFMakeCollectable(data) autorelease];
   103     else
   104         return nil;
   105 }
   106 
   107 
   108 - (CSSM_OID) contentType
   109 {
   110    NSData *data = [self _dataFromFunction: &CMSEncoderCopyEncapsulatedContentType];
   111    return (CSSM_OID){data.length,(uint8*)data.bytes};
   112 }
   113 
   114 - (void) setContentType: (CSSM_OID)contentType
   115 {
   116     checksave( CMSEncoderSetEncapsulatedContentType(_encoder, &contentType) );
   117 }
   118 
   119 
   120 - (BOOL) addData: (NSData*)data
   121 {
   122     Assert(data);
   123     return ! _error && checksave( CMSEncoderUpdateContent(_encoder, data.bytes, data.length) );
   124 }
   125 
   126 
   127 - (NSData*) encodedData
   128 {
   129     if( ! _error )
   130         return [self _dataFromFunction: &CMSEncoderCopyEncodedContent];
   131     else
   132         return nil;
   133 }
   134 
   135 
   136 + (NSData*) encodeData: (NSData*)data
   137                 signer: (MYIdentity*)signer
   138              recipient: (MYCertificate*)recipient
   139                  error: (NSError**)outError
   140 {
   141     MYEncoder *e = [[self alloc] init];
   142     if( signer )
   143         [e addSigner: signer];
   144     if( recipient )
   145         [e addRecipient: recipient];
   146     [e addData: data];
   147     *outError = e.error;
   148     NSData *result = e.encodedData;
   149     [e release];
   150     return result;
   151 }
   152 
   153 
   154 @end
   155 
   156 
   157 #if DEBUG
   158 
   159 #import "MYCrypto+Cocoa.h"
   160 
   161 TestCase(MYEncoder) {
   162     MYIdentity *me = nil;//[MYIdentity preferredIdentityForName: @"MYCryptoTest"];
   163     if (!me) {
   164         NSArray *idents = [[[MYKeychain allKeychains] enumerateIdentities] allObjects];
   165         SFChooseIdentityPanel *panel = [SFChooseIdentityPanel sharedChooseIdentityPanel];
   166         [panel setAlternateButtonTitle: @"Cancel"];
   167         if ([panel my_runModalForIdentities: idents 
   168                                     message: @"Choose an identity for the MYEncoder test case:"]
   169                 != NSOKButton) {
   170             [NSException raise: NSGenericException format: @"User canceled"];
   171         }
   172         me = [panel my_identity];
   173         [me makePreferredIdentityForName: @"MYCryptoTest"];
   174     }
   175     CAssert(me,@"No default identity has been set up in the Keychain");
   176     
   177     NSData *source = [NSData dataWithContentsOfFile: @"/Library/Desktop Pictures/Nature/Zen Garden.jpg"];
   178     CAssert(source);
   179     
   180     NSError *error;
   181     NSData *encoded;
   182     
   183     Log(@"Testing signing...");
   184     encoded = [MYEncoder encodeData: source signer: me recipient: nil error: &error];
   185     CAssertEq(error,nil);
   186     CAssert([encoded length]);
   187     Log(@"MYEncoder signed %u bytes into %u bytes", source.length,encoded.length);
   188     
   189     Log(@"Testing encryption...");
   190     encoded = [MYEncoder encodeData: source signer: nil recipient: me error: &error];
   191     CAssertEq(error,nil);
   192     CAssert([encoded length]);
   193     Log(@"MYEncoder encrypted %u bytes into %u bytes", source.length,encoded.length);
   194     
   195     Log(@"Testing signing+encryption...");
   196     encoded = [MYEncoder encodeData: source signer: me recipient: me error: &error];
   197     CAssertEq(error,nil);
   198     CAssert([encoded length]);
   199     Log(@"MYEncoder signed/encrypted %u bytes into %u bytes", source.length,encoded.length);
   200 }
   201 #endif