MYPublicKey.m
author Jens Alfke <jens@mooseyard.com>
Sat Jun 06 15:36:35 2009 -0700 (2009-06-06)
changeset 22 058394513f33
parent 17 90a70925562b
child 23 39fec79de6e8
permissions -rw-r--r--
Added a few comments. That is all.
snej@0
     1
//
snej@0
     2
//  MYPublicKey.m
snej@0
     3
//  MYCrypto
snej@0
     4
//
snej@0
     5
//  Created by Jens Alfke on 3/21/09.
snej@0
     6
//  Copyright 2009 Jens Alfke. All rights reserved.
snej@0
     7
//
snej@0
     8
snej@0
     9
#import "MYPublicKey.h"
snej@0
    10
#import "MYCrypto_Private.h"
snej@0
    11
#import "MYDigest.h"
jens@21
    12
#import "MYASN1Object.h"
jens@21
    13
#import "MYDEREncoder.h"
jens@21
    14
#import "MYBERParser.h"
snej@0
    15
#import "MYErrorUtils.h"
snej@0
    16
#import <CommonCrypto/CommonDigest.h>
snej@0
    17
snej@0
    18
snej@0
    19
#pragma mark -
snej@0
    20
@implementation MYPublicKey
snej@0
    21
snej@0
    22
jens@21
    23
- (id) initWithModulus: (NSData*)modulus exponent: (unsigned)exponent {
jens@21
    24
    // An RSA key is encoded in ASN.1 as a sequence of modulus and exponent, both as integers.
jens@21
    25
    MYASN1BigInteger *modulusInt = [[MYASN1BigInteger alloc] initWithUnsignedData: modulus];
jens@21
    26
    id asn1 = $array( modulusInt, $object(exponent) );
jens@21
    27
    [modulusInt release];
jens@21
    28
    NSData *keyData = [MYDEREncoder encodeRootObject: asn1 error: nil];
jens@21
    29
    return [self initWithKeyData: keyData];
jens@21
    30
}
jens@21
    31
jens@21
    32
snej@0
    33
- (void) dealloc
snej@0
    34
{
snej@0
    35
    [_digest release];
snej@0
    36
    [super dealloc];
snej@0
    37
}
snej@0
    38
snej@0
    39
- (SecExternalItemType) keyType {
snej@3
    40
#if MYCRYPTO_USE_IPHONE_API
snej@3
    41
    return kSecAttrKeyClassPublic;
snej@3
    42
#else
snej@0
    43
    return kSecItemTypePublicKey;
snej@3
    44
#endif
snej@0
    45
}
snej@3
    46
snej@0
    47
- (NSUInteger)hash {
snej@0
    48
    return self.publicKeyDigest.hash;
snej@0
    49
}
snej@0
    50
snej@0
    51
- (NSString*) description {
snej@0
    52
    return $sprintf(@"%@[%@]", [self class], self.publicKeyDigest.abbreviatedHexString);
snej@0
    53
}
snej@0
    54
snej@0
    55
- (MYSHA1Digest*) publicKeyDigest {
snej@0
    56
    if (!_digest)
snej@3
    57
        _digest = [[self _keyDigest] retain];
snej@0
    58
    return _digest;
snej@0
    59
}
snej@0
    60
snej@3
    61
#if !MYCRYPTO_USE_IPHONE_API
snej@13
    62
- (SecExternalFormat) _externalFormat {
snej@14
    63
    return kSecFormatBSAFE;
snej@0
    64
}
snej@3
    65
#endif
snej@0
    66
snej@0
    67
jens@21
    68
- (BOOL) getModulus: (NSData**)outModulus exponent: (unsigned*)outExponent {
jens@21
    69
    Assert(outModulus!=nil);
jens@21
    70
    Assert(outExponent!=nil);
jens@21
    71
    NSArray *asn1 = $castIf(NSArray, MYBERParse(self.keyData, nil));
jens@21
    72
    if (!asn1 || asn1.count != 2)
jens@21
    73
        return NO;
jens@21
    74
    *outModulus = $castIf(MYASN1BigInteger, [asn1 objectAtIndex: 0]).unsignedData;
jens@21
    75
    *outExponent = $castIf(NSNumber, [asn1 objectAtIndex: 1]).unsignedIntValue;
jens@21
    76
    return (*outModulus!=nil && *outExponent>=3);
jens@21
    77
}
jens@21
    78
jens@21
    79
snej@13
    80
- (NSData*) rawEncryptData: (NSData*)data {
snej@3
    81
    return [self _crypt: data operation: YES];
snej@0
    82
}
snej@0
    83
snej@0
    84
snej@0
    85
- (BOOL) verifySignature: (NSData*)signature ofData: (NSData*)data {
snej@0
    86
    Assert(data);
snej@0
    87
    Assert(signature);
snej@1
    88
    
snej@3
    89
#if MYCRYPTO_USE_IPHONE_API
snej@3
    90
    uint8_t digest[CC_SHA1_DIGEST_LENGTH];
snej@3
    91
    CC_SHA1(data.bytes,data.length, digest);
snej@3
    92
    OSStatus err = SecKeyRawVerify(self.keyRef, kSecPaddingPKCS1SHA1,
snej@3
    93
                                   digest,sizeof(digest), //data.bytes, data.length,
snej@3
    94
                                   signature.bytes, signature.length);
snej@3
    95
    return err==noErr;
snej@3
    96
    
snej@3
    97
#else
jens@17
    98
    CSSM_CC_HANDLE ccHandle = [self _createSignatureContext: CSSM_ALGID_SHA1WithRSA];
snej@0
    99
    if (!ccHandle) return NO;
snej@0
   100
    CSSM_DATA original = {data.length, (void*)data.bytes};
snej@0
   101
    CSSM_DATA sig = {signature.length, (void*)signature.bytes};
snej@0
   102
    CSSM_RETURN cssmErr = CSSM_VerifyData(ccHandle, &original, 1, CSSM_ALGID_NONE, &sig);
snej@0
   103
    CSSM_DeleteContext(ccHandle);
snej@0
   104
    if (cssmErr == CSSM_OK)
snej@0
   105
        return YES;
snej@0
   106
    if (cssmErr != CSSMERR_CSP_VERIFY_FAILED)
snej@0
   107
        Warn(@"CSSM error verifying signature: %u", MYErrorName(MYCSSMErrorDomain,cssmErr));
snej@0
   108
    return NO;
snej@3
   109
#endif
snej@0
   110
}
snej@0
   111
snej@0
   112
snej@4
   113
#if !TARGET_OS_IPHONE
snej@4
   114
- (CSSM_WRAP_KEY*) _unwrappedCSSMKey {
snej@4
   115
    const CSSM_KEY *key = self.cssmKey;
snej@4
   116
    
snej@4
   117
    if (key->KeyHeader.BlobType == CSSM_KEYBLOB_WRAPPED) {
snej@4
   118
        Warn(@"Key is already wrapped.\n");
snej@4
   119
        return NULL;
snej@4
   120
    }
snej@4
   121
    
snej@4
   122
    if (key->KeyHeader.KeyClass != CSSM_KEYCLASS_PUBLIC_KEY)
snej@4
   123
        Warn(@"Warning: Null wrapping a non-public key - this is a dangerous operation.\n");
snej@4
   124
    
snej@4
   125
    const CSSM_ACCESS_CREDENTIALS* credentials;
snej@4
   126
    credentials = [self cssmCredentialsForOperation: CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED
snej@4
   127
                                               type: kSecCredentialTypeDefault error: nil];
snej@4
   128
    CSSM_CC_HANDLE ccHandle;
snej@4
   129
    if (!checkcssm(CSSM_CSP_CreateSymmetricContext(self.cssmCSPHandle, 
snej@4
   130
                                                   CSSM_ALGID_NONE, CSSM_ALGMODE_WRAP, 
snej@4
   131
                                                   NULL, NULL, NULL, 
snej@4
   132
                                                   CSSM_PADDING_NONE, NULL, 
snej@4
   133
                                                   &ccHandle),
snej@4
   134
                   @"CSSM_CSP_CreateSymmetricContext"))
snej@4
   135
        return NULL;
snej@4
   136
                   
snej@4
   137
    CSSM_WRAP_KEY *result = malloc(sizeof(CSSM_WRAP_KEY));
snej@4
   138
    if (!checkcssm(CSSM_WrapKey(ccHandle, credentials, key, NULL, result),
snej@4
   139
                      @"CSSM_WrapKey")) {
snej@4
   140
        free(result);
snej@4
   141
        result = NULL;
snej@4
   142
    }
snej@4
   143
    CSSM_DeleteContext(ccHandle);
snej@4
   144
    return result;
snej@4
   145
}
snej@13
   146
snej@13
   147
snej@13
   148
- (NSData*) wrapSessionKey: (MYSymmetricKey*)sessionKey {
snej@13
   149
    const CSSM_ACCESS_CREDENTIALS* credentials;
snej@13
   150
    credentials = [self cssmCredentialsForOperation: CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED
snej@13
   151
                                               type: kSecCredentialTypeDefault error: nil];
snej@13
   152
    CSSM_CSP_HANDLE cspHandle = self.cssmCSPHandle;
snej@13
   153
    CSSM_CC_HANDLE ctx;
snej@13
   154
    if (!checkcssm(CSSM_CSP_CreateAsymmetricContext(cspHandle,
snej@13
   155
                                                    self.cssmAlgorithm,
snej@13
   156
                                                    credentials, 
snej@13
   157
                                                    self.cssmKey,
snej@13
   158
                                                    CSSM_PADDING_PKCS1,
snej@13
   159
                                                    &ctx), 
snej@13
   160
                   @"CSSM_CSP_CreateAsymmetricContext"))
snej@13
   161
        return nil;
snej@14
   162
        
snej@13
   163
    // Now wrap the key:
snej@13
   164
    NSData *result = nil;
snej@13
   165
    CSSM_WRAP_KEY wrappedKey = {};
snej@14
   166
    CSSM_DATA descriptiveData = {};
snej@14
   167
    if (checkcssm(CSSM_WrapKey(ctx, credentials, sessionKey.cssmKey, &descriptiveData, &wrappedKey),
snej@13
   168
                  @"CSSM_WrapKey")) {
snej@13
   169
        // ...and copy the wrapped key data to the result NSData:
snej@13
   170
        result = [NSData dataWithBytes: wrappedKey.KeyData.Data length: wrappedKey.KeyData.Length];
snej@13
   171
        CSSM_FreeKey(cspHandle, credentials, &wrappedKey, NO);
snej@13
   172
    }
snej@13
   173
    // Finally, delete the context
snej@13
   174
    CSSM_DeleteContext(ctx);
snej@13
   175
    return result;
snej@13
   176
}
snej@13
   177
snej@13
   178
snej@4
   179
#endif
snej@4
   180
snej@4
   181
snej@0
   182
@end
snej@0
   183
snej@0
   184
snej@0
   185
snej@0
   186
/*
snej@0
   187
 Copyright (c) 2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
snej@0
   188
 
snej@0
   189
 Redistribution and use in source and binary forms, with or without modification, are permitted
snej@0
   190
 provided that the following conditions are met:
snej@0
   191
 
snej@0
   192
 * Redistributions of source code must retain the above copyright notice, this list of conditions
snej@0
   193
 and the following disclaimer.
snej@0
   194
 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
snej@0
   195
 and the following disclaimer in the documentation and/or other materials provided with the
snej@0
   196
 distribution.
snej@0
   197
 
snej@0
   198
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
snej@0
   199
 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
snej@0
   200
 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
snej@0
   201
 BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
snej@0
   202
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
snej@0
   203
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
snej@0
   204
 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
snej@0
   205
 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
snej@0
   206
 */