MYIdentity.m
author Jens Alfke <jens@mooseyard.com>
Tue Jul 21 10:13:08 2009 -0700 (2009-07-21)
changeset 27 d0aadddb9c64
parent 23 39fec79de6e8
permissions -rw-r--r--
MYCertificate now checks validity of self-signed certs loaded from the keychain (because the Security framework doesn't validate self-signed certs.)
snej@4
     1
//
snej@4
     2
//  MYIdentity.m
snej@4
     3
//  MYCrypto
snej@4
     4
//
snej@4
     5
//  Created by Jens Alfke on 4/9/09.
snej@4
     6
//  Copyright 2009 Jens Alfke. All rights reserved.
snej@4
     7
//
snej@4
     8
snej@4
     9
#import "MYIdentity.h"
snej@4
    10
#import "MYCrypto_Private.h"
jens@26
    11
#import "MYDigest.h"
snej@4
    12
snej@4
    13
snej@4
    14
@implementation MYIdentity
snej@4
    15
snej@4
    16
snej@8
    17
/** Creates a MYIdentity object for an existing Keychain identity reference. */
snej@8
    18
+ (MYIdentity*) identityWithIdentityRef: (SecIdentityRef)identityRef {
snej@8
    19
    return [[[self alloc] initWithIdentityRef: identityRef] autorelease];
snej@8
    20
}
snej@8
    21
snej@4
    22
- (id) initWithIdentityRef: (SecIdentityRef)identityRef {
snej@4
    23
    Assert(identityRef);
snej@4
    24
    SecCertificateRef certificateRef;
snej@4
    25
    if (!check(SecIdentityCopyCertificate(identityRef, &certificateRef), @"SecIdentityCopyCertificate")) {
snej@4
    26
        [self release];
snej@4
    27
        return nil;
snej@4
    28
    }
snej@4
    29
    self = [super initWithCertificateRef: certificateRef];
snej@4
    30
    if (self) {
snej@4
    31
        _identityRef = identityRef;
snej@4
    32
        CFRetain(identityRef);
snej@4
    33
    }
snej@4
    34
    CFRelease(certificateRef);
snej@4
    35
    return self;
snej@4
    36
}
snej@4
    37
snej@4
    38
snej@4
    39
- (id) initWithCertificateRef: (SecCertificateRef)certificateRef {
snej@4
    40
    self = [super initWithCertificateRef: certificateRef];
snej@4
    41
    if (self) {
jens@23
    42
#if !MYCRYPTO_USE_IPHONE_API
snej@4
    43
        if (!check(SecIdentityCreateWithCertificate(NULL, certificateRef, &_identityRef),
snej@4
    44
                   @"SecIdentityCreateWithCertificate")) {
snej@4
    45
            [self release];
snej@4
    46
            return nil;
snej@4
    47
        }
jens@23
    48
#else
jens@26
    49
        MYSHA1Digest *keyDigest = self.publicKey.publicKeyDigest;
jens@26
    50
        if (!keyDigest) {
jens@26
    51
            Warn(@"MYIdentity: Couldn't get key digest of cert %@",certificateRef);
jens@26
    52
            [self release];
jens@26
    53
            return nil;
jens@26
    54
        }
jens@26
    55
        _identityRef = [self.keychain identityWithDigest: keyDigest].identityRef;
jens@26
    56
        if (!_identityRef) {
jens@26
    57
            Warn(@"MYIdentity: Couldn't look up identity for cert %@ with %@",certificateRef, keyDigest);
jens@26
    58
            [self release];
jens@26
    59
            return nil;
jens@26
    60
        }
jens@26
    61
        
jens@26
    62
        // Debugging: Make sure the cert is correct
jens@26
    63
        SecCertificateRef identitysCert = NULL;
jens@26
    64
        SecIdentityCopyCertificate(_identityRef, &identitysCert);
jens@26
    65
        CFDataRef identitysData = SecCertificateCopyData(identitysCert);
jens@26
    66
        AssertEqual(self.certificateData, (NSData*)identitysData);
jens@26
    67
        CFRelease(identitysData);
jens@26
    68
        CFRelease(identitysCert);
jens@26
    69
        
jens@26
    70
        CFRetain(_identityRef);
jens@23
    71
#endif
snej@4
    72
    }
snej@4
    73
    return self;
snej@4
    74
}
snej@4
    75
snej@4
    76
- (void) dealloc
snej@4
    77
{
snej@4
    78
    if (_identityRef) CFRelease(_identityRef);
snej@4
    79
    [super dealloc];
snej@4
    80
}
snej@4
    81
snej@4
    82
- (void) finalize
snej@4
    83
{
snej@4
    84
    if (_identityRef) CFRelease(_identityRef);
snej@4
    85
    [super finalize];
snej@4
    86
}
snej@4
    87
snej@4
    88
snej@8
    89
@synthesize identityRef=_identityRef;
snej@8
    90
snej@4
    91
- (MYPrivateKey*) privateKey {
snej@4
    92
    SecKeyRef keyRef = NULL;
snej@4
    93
    if (!check(SecIdentityCopyPrivateKey(_identityRef, &keyRef), @"SecIdentityCopyPrivateKey"))
snej@4
    94
        return NULL;
snej@4
    95
    MYPrivateKey *privateKey = [[MYPrivateKey alloc] _initWithKeyRef: keyRef
jens@23
    96
                                                           publicKey: self.publicKey];
snej@4
    97
    CFRelease(keyRef);
snej@4
    98
    return [privateKey autorelease];
snej@4
    99
}
snej@4
   100
snej@4
   101
jens@26
   102
- (BOOL) removeFromKeychain {
jens@26
   103
    return [self.privateKey removeFromKeychain] && [super removeFromKeychain];
jens@26
   104
}
jens@26
   105
jens@26
   106
snej@5
   107
#if !TARGET_OS_IPHONE
snej@5
   108
snej@4
   109
+ (MYIdentity*) preferredIdentityForName: (NSString*)name
snej@4
   110
{
snej@4
   111
    Assert(name);
snej@4
   112
    SecIdentityRef identityRef;
snej@8
   113
    OSStatus err = SecIdentityCopyPreference((CFStringRef)name, 0, NULL, &identityRef);
snej@8
   114
    if (err==errKCItemNotFound || !check(err,@"SecIdentityCopyPreference") || !identityRef)
snej@4
   115
        return nil;
snej@8
   116
    return [self identityWithIdentityRef: identityRef];
snej@4
   117
}
snej@4
   118
snej@4
   119
- (BOOL) makePreferredIdentityForName: (NSString*)name {
snej@4
   120
    Assert(name);
snej@4
   121
    return check(SecIdentitySetPreference(_identityRef, (CFStringRef)name, 0),
snej@4
   122
                 @"SecIdentitySetPreference");
snej@4
   123
}
snej@4
   124
snej@5
   125
#endif !TARGET_OS_IPHONE
snej@5
   126
snej@4
   127
@end
snej@14
   128
snej@14
   129
snej@14
   130
snej@14
   131
/*
snej@14
   132
 Copyright (c) 2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
snej@14
   133
 
snej@14
   134
 Redistribution and use in source and binary forms, with or without modification, are permitted
snej@14
   135
 provided that the following conditions are met:
snej@14
   136
 
snej@14
   137
 * Redistributions of source code must retain the above copyright notice, this list of conditions
snej@14
   138
 and the following disclaimer.
snej@14
   139
 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
snej@14
   140
 and the following disclaimer in the documentation and/or other materials provided with the
snej@14
   141
 distribution.
snej@14
   142
 
snej@14
   143
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
snej@14
   144
 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
snej@14
   145
 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
snej@14
   146
 BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
snej@14
   147
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
snej@14
   148
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
snej@14
   149
 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
snej@14
   150
 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
snej@14
   151
 */