MYKey-iPhone.m
author snej@snej.local
Sun Apr 12 22:16:14 2009 -0700 (2009-04-12)
changeset 9 aa5eb3fd6ebf
parent 2 8982b8fada63
child 16 c409dbc4f068
permissions -rw-r--r--
Doc touch-up
     1 //
     2 //  MYKey-iPhone.m
     3 //  MYCrypto-iPhone
     4 //
     5 //  Created by Jens Alfke on 4/4/09.
     6 //  Copyright 2009 Jens Alfke. All rights reserved.
     7 //
     8 
     9 
    10 #import "MYCrypto_Private.h"
    11 
    12 #if MYCRYPTO_USE_IPHONE_API
    13 
    14 #import "MYDigest.h"
    15 #import "MYErrorUtils.h"
    16 
    17 
    18 #pragma mark -
    19 @implementation MYKey
    20 
    21 
    22 - (id) initWithKeyRef: (SecKeyRef)key {
    23     return [super initWithKeychainItemRef: (SecKeychainItemRef)key];
    24 }
    25 
    26 
    27 - (id) _initWithKeyData: (NSData*)data
    28             forKeychain: (SecKeychainRef)keychain
    29 {
    30     NSDictionary *info = $dict( {(id)kSecClass, (id)kSecClassKey},
    31                                 {(id)kSecAttrKeyClass, (id)self.keyType},
    32                                 {(id)kSecValueData, data},
    33                                 {(id)kSecAttrIsPermanent, $object(keychain!=nil)},
    34                                 {(id)kSecReturnRef, $true} );
    35     SecKeyRef key;
    36     if (!check(SecItemAdd((CFDictionaryRef)info, (CFTypeRef*)&key), @"SecItemAdd"))
    37         return nil;
    38     else
    39         return [self initWithKeyRef: (SecKeyRef)key];
    40 }
    41 
    42 - (id) initWithKeyData: (NSData*)data {
    43     return [self _initWithKeyData: data forKeychain: nil];
    44 }
    45 
    46 
    47 - (SecExternalItemType) keyType {
    48     AssertAbstractMethod();
    49 }
    50 
    51 
    52 - (NSData*) keyData {
    53     NSDictionary *info = $dict( {(id)kSecClass, (id)kSecClassKey},
    54                                 {(id)kSecAttrKeyClass, (id)self.keyType},
    55                                 {(id)kSecMatchItemList, $array((id)self.keyRef)},
    56                                 {(id)kSecReturnData, $true} );
    57     CFDataRef data;
    58     if (!check(SecItemCopyMatching((CFDictionaryRef)info, (CFTypeRef*)&data), @"SecItemCopyMatching"))
    59         return nil;
    60     else
    61         return [(id)CFMakeCollectable(data) autorelease];
    62 }
    63 
    64 
    65 - (SecKeyRef) keyRef {
    66     return (SecKeyRef) self.keychainItemRef;
    67 }
    68 
    69 
    70 - (id) _attribute: (CFTypeRef)attribute {
    71     NSDictionary *info = $dict( {(id)kSecClass, (id)kSecClassKey},
    72                                 {(id)kSecAttrKeyClass, (id)self.keyType},
    73                                 {(id)kSecMatchItemList, $array((id)self.keyRef)},
    74                                 {(id)kSecReturnAttributes, $true} );
    75     CFDictionaryRef attrs = NULL;
    76     if (!check(SecItemCopyMatching((CFDictionaryRef)info, (CFTypeRef*)&attrs), @"SecItemCopyMatching"))
    77         return nil;
    78     CFTypeRef rawValue = CFDictionaryGetValue(attrs,attribute);
    79     id value = rawValue ?[[(id)CFMakeCollectable(rawValue) retain] autorelease] :nil;
    80     CFRelease(attrs);
    81     return value;
    82 }
    83 
    84 - (BOOL) setValue: (NSString*)value ofAttribute: (SecKeychainAttrType)attribute {
    85     if (!value)
    86         value = (id)[NSNull null];
    87     NSDictionary *query = $dict( {(id)kSecClass, (id)kSecClassKey},
    88                                 {(id)kSecAttrKeyClass, (id)self.keyType},
    89                                 {(id)kSecMatchItemList, self._itemList} );
    90     NSDictionary *attrs = $dict( {(id)attribute, value} );
    91     return check(SecItemUpdate((CFDictionaryRef)query, (CFDictionaryRef)attrs), @"SecItemUpdate");
    92 }
    93 
    94 
    95 - (NSString*) name {
    96     return [self _attribute: kSecAttrLabel];
    97 }
    98 
    99 - (void) setName: (NSString*)name {
   100     [self setValue: name ofAttribute: kSecAttrLabel];
   101 }
   102 
   103 - (NSString*) alias {
   104     return [self _attribute: kSecAttrApplicationTag];
   105 }
   106 
   107 - (void) setAlias: (NSString*)alias {
   108     [self setValue: alias ofAttribute: kSecAttrApplicationTag];
   109 }
   110 
   111 
   112 
   113 
   114 /** Asymmetric encryption/decryption; used by MYPublicKey and MYPrivateKey. */
   115 - (NSData*) _crypt: (NSData*)data operation: (BOOL)operation {
   116     CAssert(data);
   117     size_t dataLength = data.length;
   118     SecKeyRef key = self.keyRef;
   119     size_t outputLength = MAX(dataLength, SecKeyGetBlockSize(key));
   120     void *outputBuf = malloc(outputLength);
   121     if (!outputBuf) return nil;
   122     OSStatus err;
   123     if (operation)
   124         err = SecKeyEncrypt(key, kSecPaddingNone,//PKCS1, 
   125                             data.bytes, dataLength,
   126                             outputBuf, &outputLength);
   127     else
   128         err = SecKeyDecrypt(key, kSecPaddingNone,//PKCS1, 
   129                             data.bytes, dataLength,
   130                             outputBuf, &outputLength);
   131     if (err) {
   132         free(outputBuf);
   133         Warn(@"%scrypting failed (%i)", (operation ?"En" :"De"), err);
   134         // Note: One of the errors I've seen is -9809, which is errSSLCrypto (SecureTransport.h)
   135         return nil;
   136     } else
   137         return [NSData dataWithBytesNoCopy: outputBuf length: outputLength freeWhenDone: YES];
   138 }
   139 
   140 
   141 @end
   142 
   143 
   144 #endif MYCRYPTO_USE_IPHONE_API
   145 
   146 
   147 
   148 /*
   149  Copyright (c) 2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
   150  
   151  Redistribution and use in source and binary forms, with or without modification, are permitted
   152  provided that the following conditions are met:
   153  
   154  * Redistributions of source code must retain the above copyright notice, this list of conditions
   155  and the following disclaimer.
   156  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
   157  and the following disclaimer in the documentation and/or other materials provided with the
   158  distribution.
   159  
   160  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
   161  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
   162  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
   163  BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   164  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
   165   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   166  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
   167  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   168  */