* Added ASN.1 / BER / DER utilities, to be used in generating and parsing X.509 certs.
* Added Keychain user-interaction-allowed setter. Added doc comments to MYSymmetricKey.
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/MYASN1Object.h Tue Jun 02 13:16:28 2009 -0700
1.3 @@ -0,0 +1,63 @@
1.4 +//
1.5 +// MYASN1Object.h
1.6 +// MYCrypto-iPhone
1.7 +//
1.8 +// Created by Jens Alfke on 5/28/09.
1.9 +// Copyright 2009 Jens Alfke. All rights reserved.
1.10 +//
1.11 +
1.12 +#import <Foundation/Foundation.h>
1.13 +
1.14 +
1.15 +/** A generic ASN.1 data value. The BER parser instantiates these to represent parsed values that
1.16 + it doesn't know how to represent otherwise. */
1.17 +@interface MYASN1Object : NSObject
1.18 +{
1.19 + @private
1.20 + uint32_t _tag;
1.21 + uint8_t _tagClass;
1.22 + BOOL _constructed;
1.23 + NSData *_value;
1.24 + NSArray *_components;
1.25 +}
1.26 +
1.27 +- (id) initWithTag: (uint32_t)tag
1.28 + ofClass: (uint8_t)tagClass
1.29 + constructed: (BOOL)constructed
1.30 + value: (NSData*)value;
1.31 +- (id) initWithTag: (uint32_t)tag
1.32 + ofClass: (uint8_t)tagClass
1.33 + components: (NSArray*)components;
1.34 +
1.35 +@property (readonly) uint32_t tag;
1.36 +@property (readonly) uint8_t tagClass;
1.37 +@property (readonly) BOOL constructed;
1.38 +@property (readonly) NSData *value;
1.39 +@property (readonly) NSArray *components;
1.40 +
1.41 ++ (NSString*) dump: (id)object;
1.42 +
1.43 +@end
1.44 +
1.45 +
1.46 +/** An ASN.1 "big" (arbitrary-length) integer.
1.47 + The value contains the bytes of the integer, in big-endian order. */
1.48 +@interface MYASN1BigInteger : MYASN1Object
1.49 +@end
1.50 +
1.51 +
1.52 +/** An ordered string of bits, as used in ASN.1.
1.53 + This differs from NSData in that it need not occupy a whole number of bytes;
1.54 + that is, the number of bits need not be a multiple of 8. */
1.55 +@interface MYBitString : NSObject
1.56 +{
1.57 + NSData *_bits;
1.58 + NSUInteger _bitCount;
1.59 +}
1.60 +
1.61 +- (id)initWithBits: (NSData*)bits count: (NSUInteger)bitCount;
1.62 +
1.63 +@property (readonly, nonatomic) NSData *bits;
1.64 +@property (readonly, nonatomic) NSUInteger bitCount;
1.65 +
1.66 +@end
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/MYASN1Object.m Tue Jun 02 13:16:28 2009 -0700
2.3 @@ -0,0 +1,132 @@
2.4 +//
2.5 +// MYASN1Object.m
2.6 +// MYCrypto-iPhone
2.7 +//
2.8 +// Created by Jens Alfke on 5/28/09.
2.9 +// Copyright 2009 Jens Alfke. All rights reserved.
2.10 +//
2.11 +
2.12 +#import "MYASN1Object.h"
2.13 +
2.14 +
2.15 +@implementation MYASN1Object
2.16 +
2.17 +
2.18 +- (id) initWithTag: (uint32_t)tag
2.19 + ofClass: (uint8_t)tagClass
2.20 + constructed: (BOOL)constructed
2.21 + value: (NSData*)value
2.22 +{
2.23 + Assert(value);
2.24 + self = [super init];
2.25 + if (self != nil) {
2.26 + _tag = tag;
2.27 + _tagClass = tagClass;
2.28 + _constructed = constructed;
2.29 + _value = [value copy];
2.30 + }
2.31 + return self;
2.32 +}
2.33 +
2.34 +- (id) initWithTag: (uint32_t)tag
2.35 + ofClass: (uint8_t)tagClass
2.36 + components: (NSArray*)components
2.37 +{
2.38 + Assert(components);
2.39 + self = [super init];
2.40 + if (self != nil) {
2.41 + _tag = tag;
2.42 + _tagClass = tagClass;
2.43 + _constructed = YES;
2.44 + _components = [components copy];
2.45 + }
2.46 + return self;
2.47 +}
2.48 +
2.49 +- (void) dealloc
2.50 +{
2.51 + [_value release];
2.52 + [_components release];
2.53 + [super dealloc];
2.54 +}
2.55 +
2.56 +
2.57 +@synthesize tag=_tag, tagClass=_tagClass, constructed=_constructed, value=_value, components=_components;
2.58 +
2.59 +
2.60 +- (NSString*)description {
2.61 + if (_components)
2.62 + return $sprintf(@"%@[%hhu/%u/%u]%@", self.class, _tagClass,(unsigned)_constructed,_tag, _components);
2.63 + else
2.64 + return $sprintf(@"%@[%hhu/%u/%u, %u bytes]", self.class, _tagClass,(unsigned)_constructed,_tag, _value.length);
2.65 +}
2.66 +
2.67 +static void dump(id object, NSMutableString *output, NSString *indent) {
2.68 + if ([object isKindOfClass: [MYASN1Object class]]) {
2.69 + MYASN1Object *asn1Obj = object;
2.70 + [output appendFormat: @"%@%@[%hhu/%u]", indent, asn1Obj.class, asn1Obj.tagClass,asn1Obj.tag];
2.71 + if (asn1Obj.components) {
2.72 + [output appendString: @":\n"];
2.73 + NSString *subindent = [indent stringByAppendingString: @" "];
2.74 + for (id o in asn1Obj.components)
2.75 + dump(o,output, subindent);
2.76 + } else
2.77 + [output appendFormat: @" %@\n", asn1Obj.value];
2.78 + } else if([object respondsToSelector: @selector(objectEnumerator)]) {
2.79 + [output appendString: indent];
2.80 + if ([object isKindOfClass: [NSArray class]])
2.81 + [output appendString: @"Sequence:\n"];
2.82 + else if ([object isKindOfClass: [NSSet class]])
2.83 + [output appendString: @"Set:\n"];
2.84 + else
2.85 + [output appendFormat: @"%@:\n", [object class]];
2.86 + NSString *subindent = [indent stringByAppendingString: @" "];
2.87 + for (id o in object)
2.88 + dump(o,output, subindent);
2.89 + } else {
2.90 + [output appendFormat: @"%@%@\n", indent, object];
2.91 + }
2.92 +}
2.93 +
2.94 ++ (NSString*) dump: (id)object {
2.95 + NSMutableString *output = [NSMutableString stringWithCapacity: 512];
2.96 + dump(object,output,@"");
2.97 + return output;
2.98 +}
2.99 +
2.100 +
2.101 +@end
2.102 +
2.103 +
2.104 +
2.105 +@implementation MYASN1BigInteger
2.106 +
2.107 +@end
2.108 +
2.109 +
2.110 +
2.111 +@implementation MYBitString
2.112 +
2.113 +
2.114 +- (id)initWithBits: (NSData*)bits count: (unsigned)bitCount;
2.115 +{
2.116 + Assert(bits);
2.117 + Assert(bitCount <= 8*bits.length);
2.118 + self = [super init];
2.119 + if (self != nil) {
2.120 + _bits = [bits copy];
2.121 + _bitCount = bitCount;
2.122 + }
2.123 + return self;
2.124 +}
2.125 +
2.126 +- (void) dealloc
2.127 +{
2.128 + [_bits release];
2.129 + [super dealloc];
2.130 +}
2.131 +
2.132 +
2.133 +@synthesize bits=_bits, bitCount=_bitCount;
2.134 +
2.135 +@end
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/MYBERParser.h Tue Jun 02 13:16:28 2009 -0700
3.3 @@ -0,0 +1,19 @@
3.4 +//
3.5 +// MYBERParser.h
3.6 +// MYCrypto
3.7 +//
3.8 +// Created by Jens Alfke on 6/2/09.
3.9 +// Copyright 2009 Jens Alfke. All rights reserved.
3.10 +//
3.11 +
3.12 +#import <Cocoa/Cocoa.h>
3.13 +
3.14 +
3.15 +#define MYASN1ErrorDomain @"MYASN1ErrorDomain"
3.16 +
3.17 +
3.18 +/** Parses a block of BER-formatted data into an object tree. */
3.19 +id MYBERParse (NSData *ber, NSError **outError);
3.20 +
3.21 +NSDateFormatter* MYBERGeneralizedTimeFormatter();
3.22 +NSDateFormatter* MYBERUTCTimeFormatter();
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/MYBERParser.m Tue Jun 02 13:16:28 2009 -0700
4.3 @@ -0,0 +1,298 @@
4.4 +//
4.5 +// MYBERParser.m
4.6 +// MYCrypto
4.7 +//
4.8 +// Created by Jens Alfke on 6/2/09.
4.9 +// Copyright 2009 Jens Alfke. All rights reserved.
4.10 +//
4.11 +
4.12 +#import "MYBERParser.h"
4.13 +#import "MYASN1Object.h"
4.14 +#import "MYOID.h"
4.15 +#import "MYErrorUtils.h"
4.16 +#import "CollectionUtils.h"
4.17 +#import "Test.h"
4.18 +
4.19 +
4.20 +#define MYBERParserException @"MYBERParserException"
4.21 +
4.22 +
4.23 +
4.24 +typedef struct {
4.25 + const uint8_t *nextChar;
4.26 + size_t length;
4.27 +} InputData;
4.28 +
4.29 +
4.30 +static void requireLength (size_t length, size_t expectedLength) {
4.31 + if (length != expectedLength)
4.32 + [NSException raise: MYBERParserException format: @"Unexpected value length"];
4.33 +}
4.34 +
4.35 +
4.36 +static const void* readOrDie (InputData *input, size_t len) {
4.37 + if (len > input->length)
4.38 + [NSException raise: MYBERParserException format: @"Unexpected EOF on input"];
4.39 + const void *bytes = input->nextChar;
4.40 + input->nextChar += len;
4.41 + input->length -= len;
4.42 + return bytes;
4.43 +}
4.44 +
4.45 +
4.46 +static NSData* readDataOrDie(InputData *input, size_t length) {
4.47 + return [NSMutableData dataWithBytes: readOrDie(input,length) length: length];
4.48 +}
4.49 +
4.50 +
4.51 +static NSString* readStringOrDie(InputData *input, size_t length, NSStringEncoding encoding) {
4.52 + NSString *str = [[NSString alloc] initWithBytes: readOrDie(input,length)
4.53 + length: length
4.54 + encoding: encoding];
4.55 + if (!str)
4.56 + [NSException raise: MYBERParserException format: @"Unparseable string"];
4.57 + return [str autorelease];
4.58 +}
4.59 +
4.60 +
4.61 +static uint32_t readBigEndianUnsignedInteger (InputData *input, size_t length) {
4.62 + if (length == 0 || length > 4)
4.63 + [NSException raise: MYBERParserException format: @"Invalid integer length"];
4.64 + uint32_t result = 0;
4.65 + memcpy(((uint8_t*)&result)+(4-length), readOrDie(input, length), length);
4.66 + return result;
4.67 +}
4.68 +
4.69 +static int32_t readBigEndianSignedInteger (InputData *input, size_t length) {
4.70 + int32_t result = (int32_t) readBigEndianUnsignedInteger(input,length);
4.71 + uint8_t *dst = ((uint8_t*)&result)+(4-length);
4.72 + if (*dst & 0x80) { // sign-extend negative value
4.73 + while (--dst >= (uint8_t*)&result)
4.74 + *dst = 0xFF;
4.75 + }
4.76 + return result;
4.77 +}
4.78 +
4.79 +
4.80 +NSDateFormatter* MYBERGeneralizedTimeFormatter() {
4.81 + static NSDateFormatter *sFmt;
4.82 + if (!sFmt) {
4.83 + sFmt = [[NSDateFormatter alloc] init];
4.84 + sFmt.dateFormat = @"yyyyMMddHHmmss'Z'";
4.85 + sFmt.timeZone = [NSTimeZone timeZoneWithName: @"GMT"];
4.86 + }
4.87 + return sFmt;
4.88 +}
4.89 +
4.90 +NSDateFormatter* MYBERUTCTimeFormatter() {
4.91 + static NSDateFormatter *sFmt;
4.92 + if (!sFmt) {
4.93 + sFmt = [[NSDateFormatter alloc] init];
4.94 + sFmt.dateFormat = @"yyMMddHHmmss'Z'";
4.95 + sFmt.timeZone = [NSTimeZone timeZoneWithName: @"GMT"];
4.96 + }
4.97 + return sFmt;
4.98 +}
4.99 +
4.100 +static NSDate* parseDate (NSString *dateStr, unsigned tag) {
4.101 + NSDateFormatter *fmt = (tag==23 ?MYBERUTCTimeFormatter() :MYBERGeneralizedTimeFormatter());
4.102 + NSDate *date = [fmt dateFromString: dateStr];
4.103 + if (!date)
4.104 + [NSException raise: MYBERParserException format: @"Unparseable date '%@'", dateStr];
4.105 + return date;
4.106 +}
4.107 +
4.108 +
4.109 +static id parseBER(InputData *input) {
4.110 + struct {
4.111 + unsigned tag :5;
4.112 + unsigned isConstructed :1;
4.113 + unsigned tagClass :2;
4.114 + unsigned length :7;
4.115 + unsigned isLengthLong :1;
4.116 + } header;
4.117 + memcpy(&header, readOrDie(input,2), 2);
4.118 +
4.119 + if (header.tag == 0x1F)
4.120 + [NSException raise: MYBERParserException format: @"Long tags not supported"];
4.121 +
4.122 + // Parse the length:
4.123 + size_t length;
4.124 + if (!header.isLengthLong)
4.125 + length = header.length;
4.126 + else if (header.length == 0)
4.127 + [NSException raise: MYBERParserException format: @"Indefinite length not supported"];
4.128 + else
4.129 + length = NSSwapBigIntToHost(readBigEndianUnsignedInteger(input,header.length));
4.130 +
4.131 + Class defaultClass = [MYASN1Object class];
4.132 +
4.133 + // Tag values can be found in <Security/x509defs.h>. I'm not using them here because that
4.134 + // header does not exist on iPhone!
4.135 +
4.136 + if (header.isConstructed) {
4.137 + // Constructed:
4.138 + NSMutableArray *items = $marray();
4.139 + InputData subInput = {input->nextChar, length};
4.140 + while (subInput.length > 0) {
4.141 + [items addObject: parseBER(&subInput)];
4.142 + }
4.143 + input->nextChar += length;
4.144 + input->length -= length;
4.145 +
4.146 + switch (header.tag) {
4.147 + case 16: // sequence
4.148 + return items;
4.149 + case 17: // set
4.150 + return [NSSet setWithArray: items];
4.151 + default:
4.152 + return [[[MYASN1Object alloc] initWithTag: header.tag
4.153 + ofClass: header.tagClass
4.154 + components: items] autorelease];
4.155 + }
4.156 + } else {
4.157 + // Primitive:
4.158 + switch (header.tag) {
4.159 + case 1: { // boolean
4.160 + requireLength(length,1);
4.161 + return *(const uint8_t*)readOrDie(input, 1) ?$true :$false;
4.162 + }
4.163 + case 2: // integer
4.164 + case 10: // enum
4.165 + {
4.166 + if (length <= 4) {
4.167 + int32_t value = NSSwapBigIntToHost(readBigEndianSignedInteger(input,length));
4.168 + return [NSNumber numberWithInteger: value];
4.169 + } else {
4.170 + // Big integer!
4.171 + defaultClass = [MYASN1BigInteger class];
4.172 + break;
4.173 + }
4.174 + }
4.175 + case 3: // bitstring
4.176 + {
4.177 + UInt8 unusedBits = *(const UInt8*) readOrDie(input, 1);
4.178 + if (unusedBits)
4.179 + Log(@"Bit-string has %u unused bits", (unsigned)unusedBits);
4.180 + if (unusedBits > 7 || length < 1)
4.181 + [NSException raise: MYBERParserException format: @"Bogus bit-string"];
4.182 + return [[[MYBitString alloc] initWithBits: readDataOrDie(input, length-1)
4.183 + count: 8*(length-1) - unusedBits] autorelease];
4.184 + }
4.185 + case 4: // octetstring
4.186 + return readDataOrDie(input, length);
4.187 + case 5: // null
4.188 + requireLength(length,0);
4.189 + return [NSNull null];
4.190 + case 6: // OID
4.191 + return [[[MYOID alloc] initWithBEREncoding: readDataOrDie(input, length)] autorelease];
4.192 + case 12: // UTF8String
4.193 + return readStringOrDie(input,length,NSUTF8StringEncoding);
4.194 + case 18: // numeric string
4.195 + case 19: // printable string:
4.196 + return readStringOrDie(input,length,NSASCIIStringEncoding);
4.197 + case 23: // UTC time:
4.198 + case 24: // Generalized time:
4.199 + return parseDate(readStringOrDie(input,length,NSASCIIStringEncoding), header.tag);
4.200 + default:
4.201 + break;
4.202 + }
4.203 + }
4.204 +
4.205 + // Generic case -- create and return a MYASN1Object:
4.206 + NSData *value = readDataOrDie(input, length);
4.207 + id result = [[[defaultClass alloc] initWithTag: header.tag
4.208 + ofClass: header.tagClass
4.209 + constructed: header.isConstructed
4.210 + value: value] autorelease];
4.211 + if( defaultClass == [MYASN1Object class])
4.212 + Warn(@"parseBER: Returning default %@", result);
4.213 + return result;
4.214 +}
4.215 +
4.216 +
4.217 +id MYBERParse (NSData *ber, NSError **outError) {
4.218 + @try{
4.219 + InputData input = {ber.bytes, ber.length};
4.220 + return parseBER(&input);
4.221 + }@catch (NSException *x) {
4.222 + if ($equal(x.name, MYBERParserException)) {
4.223 + *outError = MYError(1,MYASN1ErrorDomain, @"%@", x.reason);
4.224 + } else {
4.225 + @throw(x);
4.226 + }
4.227 + }
4.228 + return nil;
4.229 +}
4.230 +
4.231 +
4.232 +
4.233 +
4.234 +#pragma mark -
4.235 +#pragma mark TEST CASES:
4.236 +
4.237 +
4.238 +#define $data(BYTES...) ({const uint8_t bytes[] = {BYTES}; [NSData dataWithBytes: bytes length: sizeof(bytes)];})
4.239 +
4.240 +TestCase(ParseBER) {
4.241 + CAssertEqual(MYBERParse($data(0x05, 0x00), nil),
4.242 + [NSNull null]);
4.243 + CAssertEqual(MYBERParse($data(0x01, 0x01, 0xFF), nil),
4.244 + $true);
4.245 + CAssertEqual(MYBERParse($data(0x01, 0x01, 0x00), nil),
4.246 + $false);
4.247 +
4.248 + // integers:
4.249 + CAssertEqual(MYBERParse($data(0x02, 0x01, 0x00), nil),
4.250 + $object(0));
4.251 + CAssertEqual(MYBERParse($data(0x02, 0x01, 0x48), nil),
4.252 + $object(72));
4.253 + CAssertEqual(MYBERParse($data(0x02, 0x01, 0x80), nil),
4.254 + $object(-128));
4.255 + CAssertEqual(MYBERParse($data(0x02, 0x02, 0x00, 0x80), nil),
4.256 + $object(128));
4.257 + CAssertEqual(MYBERParse($data(0x02, 0x02, 0x30,0x39), nil),
4.258 + $object(12345));
4.259 + CAssertEqual(MYBERParse($data(0x02, 0x02, 0xCF, 0xC7), nil),
4.260 + $object(-12345));
4.261 + CAssertEqual(MYBERParse($data(0x02, 0x04, 0x07, 0x5B, 0xCD, 0x15), nil),
4.262 + $object(123456789));
4.263 + CAssertEqual(MYBERParse($data(0x02, 0x04, 0xF8, 0xA4, 0x32, 0xEB), nil),
4.264 + $object(-123456789));
4.265 + CAssertEqual(MYBERParse($data(0x02, 0x04, 0xF8, 0xA4, 0x32, 0xEB), nil),
4.266 + $object(-123456789));
4.267 +
4.268 + // octet strings:
4.269 + CAssertEqual(MYBERParse($data(0x04, 0x05, 'h', 'e', 'l', 'l', 'o'), nil),
4.270 + [@"hello" dataUsingEncoding: NSASCIIStringEncoding]);
4.271 + CAssertEqual(MYBERParse($data(0x04, 0x00), nil),
4.272 + [NSData data]);
4.273 + CAssertEqual(MYBERParse($data(0x0C, 0x05, 'h', 'e', 'l', 'l', 'o'), nil),
4.274 + @"hello");
4.275 +
4.276 + // sequences:
4.277 + CAssertEqual(MYBERParse($data(0x30, 0x06, 0x02, 0x01, 0x48, 0x01, 0x01, 0xFF), nil),
4.278 + $array($object(72), $true));
4.279 + CAssertEqual(MYBERParse($data(0x30, 0x10,
4.280 + 0x30, 0x06, 0x02, 0x01, 0x48, 0x01, 0x01, 0xFF,
4.281 + 0x30, 0x06, 0x02, 0x01, 0x48, 0x01, 0x01, 0xFF), nil),
4.282 + $array( $array($object(72), $true), $array($object(72), $true)));
4.283 +}
4.284 +
4.285 +
4.286 +TestCase(ParseCert) {
4.287 + NSData *cert = [NSData dataWithContentsOfFile: @"../../Tests/selfsigned.cer"];
4.288 + NSError *error = nil;
4.289 + id parsed = MYBERParse(cert,&error);
4.290 + CAssert(parsed);
4.291 + CAssertNil(error);
4.292 + NSString *dump = [MYASN1Object dump: parsed];
4.293 + CAssert(dump);
4.294 +
4.295 + cert = [NSData dataWithContentsOfFile: @"../../Tests/iphonedev.cer"];
4.296 + parsed = MYBERParse(cert,&error);
4.297 + CAssert(parsed);
4.298 + CAssertNil(error);
4.299 + dump = [MYASN1Object dump: parsed];
4.300 + CAssert(dump);
4.301 +}
5.1 --- a/MYCertificate.h Sun Apr 19 22:05:51 2009 -0700
5.2 +++ b/MYCertificate.h Tue Jun 02 13:16:28 2009 -0700
5.3 @@ -12,7 +12,7 @@
5.4 #import <Security/cssmtype.h>
5.5 #endif
5.6
5.7 -@class MYPublicKey;
5.8 +@class MYPublicKey, MYIdentity;
5.9
5.10
5.11 /** An X.509 certificate. */
5.12 @@ -57,6 +57,9 @@
5.13 type: (CSSM_CERT_TYPE) type
5.14 encoding: (CSSM_CERT_ENCODING) encoding;
5.15
5.16 +/** The Identity (if any) that this Certificate is part of. */
5.17 +@property (readonly) MYIdentity *identity;
5.18 +
5.19 /** The list (if any) of the subject's email addresses. */
5.20 @property (readonly) NSArray *emailAddresses;
5.21
6.1 --- a/MYCertificate.m Sun Apr 19 22:05:51 2009 -0700
6.2 +++ b/MYCertificate.m Tue Jun 02 13:16:28 2009 -0700
6.3 @@ -8,6 +8,7 @@
6.4
6.5 #import "MYCertificate.h"
6.6 #import "MYCrypto_Private.h"
6.7 +#import "MYIdentity.h"
6.8 #import "MYDigest.h"
6.9 #import "MYErrorUtils.h"
6.10
6.11 @@ -103,6 +104,10 @@
6.12 return key;
6.13 }
6.14
6.15 +- (MYIdentity*) identity {
6.16 + return [[[MYIdentity alloc] initWithCertificateRef: _certificateRef] autorelease];
6.17 +}
6.18 +
6.19 - (NSString*) commonName {
6.20 CFStringRef name = NULL;
6.21 if (!check(SecCertificateCopyCommonName(_certificateRef, &name),
7.1 --- a/MYCrypto-iPhone.xcodeproj/project.pbxproj Sun Apr 19 22:05:51 2009 -0700
7.2 +++ b/MYCrypto-iPhone.xcodeproj/project.pbxproj Tue Jun 02 13:16:28 2009 -0700
7.3 @@ -23,6 +23,7 @@
7.4 276FB34B0F856CA400CB326E /* MYCertificate.m in Sources */ = {isa = PBXBuildFile; fileRef = 276FB34A0F856CA400CB326E /* MYCertificate.m */; };
7.5 27A430120F87C6C10063D362 /* MYKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 27E823110F81D56E0019BE60 /* MYKey.m */; };
7.6 27A430140F87C6D50063D362 /* MYSymmetricKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 27A430130F87C6D50063D362 /* MYSymmetricKey.m */; };
7.7 + 27B8522D0FCEE6F9005631F9 /* MYASN1.m in Sources */ = {isa = PBXBuildFile; fileRef = 27B8522C0FCEE6F9005631F9 /* MYASN1.m */; };
7.8 27E3A6AA0F91B8B30079D4D9 /* MYCryptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 27E3A6A70F91B8B30079D4D9 /* MYCryptor.m */; };
7.9 27E823240F81D56E0019BE60 /* MYKeychainItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 27E823150F81D56E0019BE60 /* MYKeychainItem.m */; };
7.10 27E823270F81D56E0019BE60 /* MYDigest.m in Sources */ = {isa = PBXBuildFile; fileRef = 27E8231C0F81D56E0019BE60 /* MYDigest.m */; };
7.11 @@ -60,6 +61,8 @@
7.12 27A430130F87C6D50063D362 /* MYSymmetricKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYSymmetricKey.m; sourceTree = "<group>"; };
7.13 27A430150F87C6DB0063D362 /* MYSymmetricKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYSymmetricKey.h; sourceTree = "<group>"; };
7.14 27AAD9710F8927DB0064DD7C /* MYCryptoConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYCryptoConfig.h; sourceTree = "<group>"; };
7.15 + 27B8522B0FCEE6F9005631F9 /* MYASN1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYASN1.h; sourceTree = "<group>"; };
7.16 + 27B8522C0FCEE6F9005631F9 /* MYASN1.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYASN1.m; sourceTree = "<group>"; };
7.17 27E3A6A60F91B8B30079D4D9 /* MYCryptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYCryptor.h; sourceTree = "<group>"; };
7.18 27E3A6A70F91B8B30079D4D9 /* MYCryptor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYCryptor.m; sourceTree = "<group>"; };
7.19 27E8230C0F81D56E0019BE60 /* MYCertificate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYCertificate.h; sourceTree = "<group>"; };
7.20 @@ -139,6 +142,8 @@
7.21 27E8230B0F81D56E0019BE60 /* Source */ = {
7.22 isa = PBXGroup;
7.23 children = (
7.24 + 27B8522B0FCEE6F9005631F9 /* MYASN1.h */,
7.25 + 27B8522C0FCEE6F9005631F9 /* MYASN1.m */,
7.26 27AAD9710F8927DB0064DD7C /* MYCryptoConfig.h */,
7.27 27E8230C0F81D56E0019BE60 /* MYCertificate.h */,
7.28 276FB34A0F856CA400CB326E /* MYCertificate.m */,
7.29 @@ -290,6 +295,7 @@
7.30 27059CF30F8F0F9200A8422F /* MYIdentity.m in Sources */,
7.31 27E3A6AA0F91B8B30079D4D9 /* MYCryptor.m in Sources */,
7.32 274110090F99234100AD413F /* MYSymmetricKey-iPhone.m in Sources */,
7.33 + 27B8522D0FCEE6F9005631F9 /* MYASN1.m in Sources */,
7.34 );
7.35 runOnlyForDeploymentPostprocessing = 0;
7.36 };
7.37 @@ -335,7 +341,7 @@
7.38 ONLY_ACTIVE_ARCH = YES;
7.39 PREBINDING = NO;
7.40 "PROVISIONING_PROFILE[sdk=iphoneos*]" = "84D61190-B2EB-4F8E-A189-99F18EE9A07E";
7.41 - SDKROOT = iphoneos3.0;
7.42 + SDKROOT = iphonesimulator2.2.1;
7.43 };
7.44 name = Debug;
7.45 };
7.46 @@ -348,7 +354,7 @@
7.47 GCC_WARN_ABOUT_RETURN_TYPE = YES;
7.48 GCC_WARN_UNUSED_VARIABLE = YES;
7.49 PREBINDING = NO;
7.50 - SDKROOT = iphoneos3.0;
7.51 + SDKROOT = iphonesimulator2.2.1;
7.52 };
7.53 name = Release;
7.54 };
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/MYCrypto.h Tue Jun 02 13:16:28 2009 -0700
8.3 @@ -0,0 +1,15 @@
8.4 +//
8.5 +// MYCrypto.h
8.6 +// MYCrypto
8.7 +//
8.8 +// Created by Jens Alfke on 5/12/09.
8.9 +// Copyright 2009 Jens Alfke. All rights reserved.
8.10 +//
8.11 +
8.12 +
8.13 +#import "MYDigest.h"
8.14 +#import "MYKeychain.h"
8.15 +#import "MYSymmetricKey.h"
8.16 +#import "MYPublicKey.h"
8.17 +#import "MYPrivateKey.h"
8.18 +#import "MYIdentity.h"
9.1 --- a/MYCrypto.xcodeproj/project.pbxproj Sun Apr 19 22:05:51 2009 -0700
9.2 +++ b/MYCrypto.xcodeproj/project.pbxproj Tue Jun 02 13:16:28 2009 -0700
9.3 @@ -11,6 +11,39 @@
9.4 27059D770F8FA23100A8422F /* MYCrypto+Cocoa.m in Sources */ = {isa = PBXBuildFile; fileRef = 27059D760F8FA23100A8422F /* MYCrypto+Cocoa.m */; };
9.5 27059D840F8FA82500A8422F /* SecurityInterface.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27059D830F8FA82500A8422F /* SecurityInterface.framework */; };
9.6 27059DE50F8FAF6500A8422F /* MYDecoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 27059D520F8F9BB500A8422F /* MYDecoder.m */; };
9.7 + 2706F1AE0F9D3C7100292CCF /* MYCertificate.h in Headers */ = {isa = PBXBuildFile; fileRef = 27CFF4B10F7E8535000B418E /* MYCertificate.h */; };
9.8 + 2706F1AF0F9D3C7100292CCF /* MYCertificate.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CFF4B20F7E8535000B418E /* MYCertificate.m */; };
9.9 + 2706F1B00F9D3C7200292CCF /* MYCrypto+Cocoa.h in Headers */ = {isa = PBXBuildFile; fileRef = 27059D750F8FA23100A8422F /* MYCrypto+Cocoa.h */; };
9.10 + 2706F1B10F9D3C7300292CCF /* MYCrypto+Cocoa.m in Sources */ = {isa = PBXBuildFile; fileRef = 27059D760F8FA23100A8422F /* MYCrypto+Cocoa.m */; };
9.11 + 2706F1B20F9D3C7400292CCF /* MYCryptoConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 27AAD97B0F892A0D0064DD7C /* MYCryptoConfig.h */; };
9.12 + 2706F1B30F9D3C7600292CCF /* MYDigest.h in Headers */ = {isa = PBXBuildFile; fileRef = 27CFF4BF0F7E8535000B418E /* MYDigest.h */; };
9.13 + 2706F1B40F9D3C7700292CCF /* MYDigest.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CFF4C00F7E8535000B418E /* MYDigest.m */; };
9.14 + 2706F1B50F9D3C7700292CCF /* MYIdentity.h in Headers */ = {isa = PBXBuildFile; fileRef = 274863A00F8EF39400FE617B /* MYIdentity.h */; };
9.15 + 2706F1B60F9D3C7800292CCF /* MYIdentity.m in Sources */ = {isa = PBXBuildFile; fileRef = 274863A10F8EF39400FE617B /* MYIdentity.m */; };
9.16 + 2706F1B70F9D3C7900292CCF /* MYKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 27E822A00F81C5660019BE60 /* MYKey.h */; };
9.17 + 2706F1B80F9D3C7A00292CCF /* MYKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 27E822A10F81C5660019BE60 /* MYKey.m */; };
9.18 + 2706F1B90F9D3C7C00292CCF /* MYKeychain.h in Headers */ = {isa = PBXBuildFile; fileRef = 27CFF4B50F7E8535000B418E /* MYKeychain.h */; };
9.19 + 2706F1BA0F9D3C7D00292CCF /* MYKeychain.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CFF4B60F7E8535000B418E /* MYKeychain.m */; };
9.20 + 2706F1BB0F9D3C7D00292CCF /* MYKeychainItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 27CFF4B70F7E8535000B418E /* MYKeychainItem.h */; };
9.21 + 2706F1BC0F9D3C7E00292CCF /* MYKeychainItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CFF4B80F7E8535000B418E /* MYKeychainItem.m */; };
9.22 + 2706F1BD0F9D3C7E00292CCF /* MYPrivateKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 270B879D0F8C565000C56781 /* MYPrivateKey.h */; };
9.23 + 2706F1BE0F9D3C7F00292CCF /* MYPrivateKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 270B879E0F8C565000C56781 /* MYPrivateKey.m */; };
9.24 + 2706F1BF0F9D3C8000292CCF /* MYPublicKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 27CFF4BC0F7E8535000B418E /* MYPublicKey.h */; };
9.25 + 2706F1C00F9D3C8000292CCF /* MYPublicKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CFF4BD0F7E8535000B418E /* MYPublicKey.m */; };
9.26 + 2706F1C10F9D3C8100292CCF /* MYSymmetricKey-iPhone.m in Sources */ = {isa = PBXBuildFile; fileRef = 27410FEF0F99200A00AD413F /* MYSymmetricKey-iPhone.m */; };
9.27 + 2706F1C20F9D3C8200292CCF /* MYSymmetricKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 27A42D400F858ED80063D362 /* MYSymmetricKey.h */; };
9.28 + 2706F1C30F9D3C8300292CCF /* MYSymmetricKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 27A42D410F858ED80063D362 /* MYSymmetricKey.m */; };
9.29 + 2706F1C40F9D3C8800292CCF /* MYCryptor.h in Headers */ = {isa = PBXBuildFile; fileRef = 27CFF4B30F7E8535000B418E /* MYCryptor.h */; };
9.30 + 2706F1C50F9D3C8900292CCF /* MYCryptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CFF4B40F7E8535000B418E /* MYCryptor.m */; };
9.31 + 2706F1C60F9D3C8900292CCF /* MYDecoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 27059D510F8F9BB500A8422F /* MYDecoder.h */; };
9.32 + 2706F1C70F9D3C8A00292CCF /* MYDecoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 27059D520F8F9BB500A8422F /* MYDecoder.m */; };
9.33 + 2706F1C80F9D3C8B00292CCF /* MYEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 27059D4F0F8F9BB500A8422F /* MYEncoder.h */; };
9.34 + 2706F1C90F9D3C8B00292CCF /* MYEncoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 27059D500F8F9BB500A8422F /* MYEncoder.m */; };
9.35 + 2706F1CA0F9D3C9200292CCF /* MYCertGen.h in Headers */ = {isa = PBXBuildFile; fileRef = 27A42ECC0F8689D30063D362 /* MYCertGen.h */; };
9.36 + 2706F1CB0F9D3C9300292CCF /* MYCertGen.m in Sources */ = {isa = PBXBuildFile; fileRef = 27A42ECD0F8689D30063D362 /* MYCertGen.m */; };
9.37 + 270A7A730FD58FF200770C4D /* MYBERParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 270A7A710FD58FF200770C4D /* MYBERParser.h */; };
9.38 + 270A7A740FD58FF200770C4D /* MYBERParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 270A7A720FD58FF200770C4D /* MYBERParser.m */; };
9.39 + 270A7A750FD58FF200770C4D /* MYBERParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 270A7A720FD58FF200770C4D /* MYBERParser.m */; };
9.40 270B879F0F8C565000C56781 /* MYPrivateKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 270B879E0F8C565000C56781 /* MYPrivateKey.m */; };
9.41 27410FF00F99200A00AD413F /* MYSymmetricKey-iPhone.m in Sources */ = {isa = PBXBuildFile; fileRef = 27410FEF0F99200A00AD413F /* MYSymmetricKey-iPhone.m */; };
9.42 274861D50F8E4B5200FE617B /* MYCertGen.m in Sources */ = {isa = PBXBuildFile; fileRef = 27A42ECD0F8689D30063D362 /* MYCertGen.m */; };
9.43 @@ -18,6 +51,15 @@
9.44 27A42CBF0F8578B40063D362 /* MYCryptoTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 27A42CBE0F8578B40063D362 /* MYCryptoTest.m */; };
9.45 27A42D1E0F8586CE0063D362 /* MYKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 27E822A10F81C5660019BE60 /* MYKey.m */; };
9.46 27A42D420F858ED80063D362 /* MYSymmetricKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 27A42D410F858ED80063D362 /* MYSymmetricKey.m */; };
9.47 + 27B852F50FCF4EB7005631F9 /* MYASN1Object.m in Sources */ = {isa = PBXBuildFile; fileRef = 27B852F40FCF4EB7005631F9 /* MYASN1Object.m */; };
9.48 + 27B852F60FCF4EB7005631F9 /* MYASN1Object.h in Headers */ = {isa = PBXBuildFile; fileRef = 27B852F30FCF4EB6005631F9 /* MYASN1Object.h */; };
9.49 + 27B852F70FCF4EB7005631F9 /* MYASN1Object.m in Sources */ = {isa = PBXBuildFile; fileRef = 27B852F40FCF4EB7005631F9 /* MYASN1Object.m */; };
9.50 + 27B852FE0FCF4ECB005631F9 /* MYOID.h in Headers */ = {isa = PBXBuildFile; fileRef = 27B852FC0FCF4ECB005631F9 /* MYOID.h */; };
9.51 + 27B852FF0FCF4ECB005631F9 /* MYOID.m in Sources */ = {isa = PBXBuildFile; fileRef = 27B852FD0FCF4ECB005631F9 /* MYOID.m */; };
9.52 + 27B853000FCF4ECB005631F9 /* MYOID.m in Sources */ = {isa = PBXBuildFile; fileRef = 27B852FD0FCF4ECB005631F9 /* MYOID.m */; };
9.53 + 27B855270FD077A6005631F9 /* MYDEREncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 27B855250FD077A6005631F9 /* MYDEREncoder.h */; };
9.54 + 27B855280FD077A7005631F9 /* MYDEREncoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 27B855260FD077A6005631F9 /* MYDEREncoder.m */; };
9.55 + 27B855290FD077A7005631F9 /* MYDEREncoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 27B855260FD077A6005631F9 /* MYDEREncoder.m */; };
9.56 27CFF4C10F7E8535000B418E /* MYCertificate.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CFF4B20F7E8535000B418E /* MYCertificate.m */; };
9.57 27CFF4C20F7E8535000B418E /* MYCryptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CFF4B40F7E8535000B418E /* MYCryptor.m */; };
9.58 27CFF4C30F7E8535000B418E /* MYKeychain.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CFF4B60F7E8535000B418E /* MYKeychain.m */; };
9.59 @@ -32,6 +74,7 @@
9.60 27CFF5220F7E94DF000B418E /* MYCrypto_main.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CFF5210F7E94DF000B418E /* MYCrypto_main.m */; };
9.61 27CFF5760F7E999B000B418E /* MYErrorUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CFF5750F7E999B000B418E /* MYErrorUtils.m */; };
9.62 27E820720F7EA6260019BE60 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27E820710F7EA6260019BE60 /* CoreServices.framework */; };
9.63 + 27FEB3E70FBA63D200290049 /* MYCrypto.h in Headers */ = {isa = PBXBuildFile; fileRef = 27FEB3E60FBA63D200290049 /* MYCrypto.h */; };
9.64 8DD76F9C0486AA7600D96B5E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08FB779EFE84155DC02AAC07 /* Foundation.framework */; };
9.65 /* End PBXBuildFile section */
9.66
9.67 @@ -56,6 +99,9 @@
9.68 27059D750F8FA23100A8422F /* MYCrypto+Cocoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MYCrypto+Cocoa.h"; sourceTree = "<group>"; };
9.69 27059D760F8FA23100A8422F /* MYCrypto+Cocoa.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MYCrypto+Cocoa.m"; sourceTree = "<group>"; };
9.70 27059D830F8FA82500A8422F /* SecurityInterface.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SecurityInterface.framework; path = /System/Library/Frameworks/SecurityInterface.framework; sourceTree = "<absolute>"; };
9.71 + 2706F1AB0F9D3C5F00292CCF /* libMYCrypto.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libMYCrypto.a; sourceTree = BUILT_PRODUCTS_DIR; };
9.72 + 270A7A710FD58FF200770C4D /* MYBERParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYBERParser.h; sourceTree = "<group>"; };
9.73 + 270A7A720FD58FF200770C4D /* MYBERParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYBERParser.m; sourceTree = "<group>"; };
9.74 270B879D0F8C565000C56781 /* MYPrivateKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYPrivateKey.h; sourceTree = "<group>"; };
9.75 270B879E0F8C565000C56781 /* MYPrivateKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYPrivateKey.m; sourceTree = "<group>"; };
9.76 27410FEF0F99200A00AD413F /* MYSymmetricKey-iPhone.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MYSymmetricKey-iPhone.m"; sourceTree = "<group>"; };
9.77 @@ -68,6 +114,12 @@
9.78 27A42ECC0F8689D30063D362 /* MYCertGen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYCertGen.h; sourceTree = "<group>"; };
9.79 27A42ECD0F8689D30063D362 /* MYCertGen.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYCertGen.m; sourceTree = "<group>"; };
9.80 27AAD97B0F892A0D0064DD7C /* MYCryptoConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYCryptoConfig.h; sourceTree = "<group>"; };
9.81 + 27B852F30FCF4EB6005631F9 /* MYASN1Object.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYASN1Object.h; sourceTree = "<group>"; };
9.82 + 27B852F40FCF4EB7005631F9 /* MYASN1Object.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYASN1Object.m; sourceTree = "<group>"; };
9.83 + 27B852FC0FCF4ECB005631F9 /* MYOID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYOID.h; sourceTree = "<group>"; };
9.84 + 27B852FD0FCF4ECB005631F9 /* MYOID.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYOID.m; sourceTree = "<group>"; };
9.85 + 27B855250FD077A6005631F9 /* MYDEREncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYDEREncoder.h; sourceTree = "<group>"; };
9.86 + 27B855260FD077A6005631F9 /* MYDEREncoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYDEREncoder.m; sourceTree = "<group>"; };
9.87 27CFF4B10F7E8535000B418E /* MYCertificate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYCertificate.h; sourceTree = "<group>"; };
9.88 27CFF4B20F7E8535000B418E /* MYCertificate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYCertificate.m; sourceTree = "<group>"; };
9.89 27CFF4B30F7E8535000B418E /* MYCryptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYCryptor.h; sourceTree = "<group>"; };
9.90 @@ -100,10 +152,18 @@
9.91 27E822A00F81C5660019BE60 /* MYKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYKey.h; sourceTree = "<group>"; };
9.92 27E822A10F81C5660019BE60 /* MYKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYKey.m; sourceTree = "<group>"; };
9.93 27EAF0390F8B2D700091AF95 /* README.textile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.textile; sourceTree = "<group>"; };
9.94 + 27FEB3E60FBA63D200290049 /* MYCrypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYCrypto.h; sourceTree = "<group>"; };
9.95 8DD76FA10486AA7600D96B5E /* MYCrypto */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = MYCrypto; sourceTree = BUILT_PRODUCTS_DIR; };
9.96 /* End PBXFileReference section */
9.97
9.98 /* Begin PBXFrameworksBuildPhase section */
9.99 + 2706F1A90F9D3C5F00292CCF /* Frameworks */ = {
9.100 + isa = PBXFrameworksBuildPhase;
9.101 + buildActionMask = 2147483647;
9.102 + files = (
9.103 + );
9.104 + runOnlyForDeploymentPostprocessing = 0;
9.105 + };
9.106 8DD76F9B0486AA7600D96B5E /* Frameworks */ = {
9.107 isa = PBXFrameworksBuildPhase;
9.108 buildActionMask = 2147483647;
9.109 @@ -123,7 +183,7 @@
9.110 children = (
9.111 08FB7795FE84155DC02AAC07 /* Source */,
9.112 27059D4E0F8F9B9E00A8422F /* Encryption */,
9.113 - 274861440F8D757600FE617B /* Certificate Generation */,
9.114 + 274861440F8D757600FE617B /* Certificates */,
9.115 270B881C0F8D055A00C56781 /* Internal */,
9.116 27CFF4CC0F7E86E8000B418E /* MYUtilities */,
9.117 C6859EA2029092E104C91782 /* Documentation */,
9.118 @@ -162,6 +222,7 @@
9.119 27059D750F8FA23100A8422F /* MYCrypto+Cocoa.h */,
9.120 27059D760F8FA23100A8422F /* MYCrypto+Cocoa.m */,
9.121 27EAF0390F8B2D700091AF95 /* README.textile */,
9.122 + 27FEB3E60FBA63D200290049 /* MYCrypto.h */,
9.123 );
9.124 name = Source;
9.125 sourceTree = "<group>";
9.126 @@ -178,6 +239,7 @@
9.127 isa = PBXGroup;
9.128 children = (
9.129 8DD76FA10486AA7600D96B5E /* MYCrypto */,
9.130 + 2706F1AB0F9D3C5F00292CCF /* libMYCrypto.a */,
9.131 );
9.132 name = Products;
9.133 sourceTree = "<group>";
9.134 @@ -208,13 +270,21 @@
9.135 name = Internal;
9.136 sourceTree = "<group>";
9.137 };
9.138 - 274861440F8D757600FE617B /* Certificate Generation */ = {
9.139 + 274861440F8D757600FE617B /* Certificates */ = {
9.140 isa = PBXGroup;
9.141 children = (
9.142 27A42ECC0F8689D30063D362 /* MYCertGen.h */,
9.143 27A42ECD0F8689D30063D362 /* MYCertGen.m */,
9.144 + 27B852F30FCF4EB6005631F9 /* MYASN1Object.h */,
9.145 + 27B852F40FCF4EB7005631F9 /* MYASN1Object.m */,
9.146 + 270A7A710FD58FF200770C4D /* MYBERParser.h */,
9.147 + 270A7A720FD58FF200770C4D /* MYBERParser.m */,
9.148 + 27B855250FD077A6005631F9 /* MYDEREncoder.h */,
9.149 + 27B855260FD077A6005631F9 /* MYDEREncoder.m */,
9.150 + 27B852FC0FCF4ECB005631F9 /* MYOID.h */,
9.151 + 27B852FD0FCF4ECB005631F9 /* MYOID.m */,
9.152 );
9.153 - name = "Certificate Generation";
9.154 + name = Certificates;
9.155 sourceTree = "<group>";
9.156 };
9.157 27CFF4CC0F7E86E8000B418E /* MYUtilities */ = {
9.158 @@ -244,7 +314,54 @@
9.159 };
9.160 /* End PBXGroup section */
9.161
9.162 +/* Begin PBXHeadersBuildPhase section */
9.163 + 2706F1A70F9D3C5F00292CCF /* Headers */ = {
9.164 + isa = PBXHeadersBuildPhase;
9.165 + buildActionMask = 2147483647;
9.166 + files = (
9.167 + 2706F1AE0F9D3C7100292CCF /* MYCertificate.h in Headers */,
9.168 + 2706F1B00F9D3C7200292CCF /* MYCrypto+Cocoa.h in Headers */,
9.169 + 2706F1B20F9D3C7400292CCF /* MYCryptoConfig.h in Headers */,
9.170 + 2706F1B30F9D3C7600292CCF /* MYDigest.h in Headers */,
9.171 + 2706F1B50F9D3C7700292CCF /* MYIdentity.h in Headers */,
9.172 + 2706F1B70F9D3C7900292CCF /* MYKey.h in Headers */,
9.173 + 2706F1B90F9D3C7C00292CCF /* MYKeychain.h in Headers */,
9.174 + 2706F1BB0F9D3C7D00292CCF /* MYKeychainItem.h in Headers */,
9.175 + 2706F1BD0F9D3C7E00292CCF /* MYPrivateKey.h in Headers */,
9.176 + 2706F1BF0F9D3C8000292CCF /* MYPublicKey.h in Headers */,
9.177 + 2706F1C20F9D3C8200292CCF /* MYSymmetricKey.h in Headers */,
9.178 + 2706F1C40F9D3C8800292CCF /* MYCryptor.h in Headers */,
9.179 + 2706F1C60F9D3C8900292CCF /* MYDecoder.h in Headers */,
9.180 + 2706F1C80F9D3C8B00292CCF /* MYEncoder.h in Headers */,
9.181 + 2706F1CA0F9D3C9200292CCF /* MYCertGen.h in Headers */,
9.182 + 27FEB3E70FBA63D200290049 /* MYCrypto.h in Headers */,
9.183 + 27B852F60FCF4EB7005631F9 /* MYASN1Object.h in Headers */,
9.184 + 27B852FE0FCF4ECB005631F9 /* MYOID.h in Headers */,
9.185 + 27B855270FD077A6005631F9 /* MYDEREncoder.h in Headers */,
9.186 + 270A7A730FD58FF200770C4D /* MYBERParser.h in Headers */,
9.187 + );
9.188 + runOnlyForDeploymentPostprocessing = 0;
9.189 + };
9.190 +/* End PBXHeadersBuildPhase section */
9.191 +
9.192 /* Begin PBXNativeTarget section */
9.193 + 2706F1AA0F9D3C5F00292CCF /* Static Lib */ = {
9.194 + isa = PBXNativeTarget;
9.195 + buildConfigurationList = 2706F1CE0F9D3CDD00292CCF /* Build configuration list for PBXNativeTarget "Static Lib" */;
9.196 + buildPhases = (
9.197 + 2706F1A70F9D3C5F00292CCF /* Headers */,
9.198 + 2706F1A80F9D3C5F00292CCF /* Sources */,
9.199 + 2706F1A90F9D3C5F00292CCF /* Frameworks */,
9.200 + );
9.201 + buildRules = (
9.202 + );
9.203 + dependencies = (
9.204 + );
9.205 + name = "Static Lib";
9.206 + productName = "Static Lib";
9.207 + productReference = 2706F1AB0F9D3C5F00292CCF /* libMYCrypto.a */;
9.208 + productType = "com.apple.product-type.library.static";
9.209 + };
9.210 8DD76F960486AA7600D96B5E /* MYCrypto */ = {
9.211 isa = PBXNativeTarget;
9.212 buildConfigurationList = 1DEB927408733DD40010E9CD /* Build configuration list for PBXNativeTarget "MYCrypto" */;
9.213 @@ -277,6 +394,7 @@
9.214 projectRoot = "";
9.215 targets = (
9.216 8DD76F960486AA7600D96B5E /* MYCrypto */,
9.217 + 2706F1AA0F9D3C5F00292CCF /* Static Lib */,
9.218 );
9.219 };
9.220 /* End PBXProject section */
9.221 @@ -299,6 +417,32 @@
9.222 /* End PBXShellScriptBuildPhase section */
9.223
9.224 /* Begin PBXSourcesBuildPhase section */
9.225 + 2706F1A80F9D3C5F00292CCF /* Sources */ = {
9.226 + isa = PBXSourcesBuildPhase;
9.227 + buildActionMask = 2147483647;
9.228 + files = (
9.229 + 2706F1AF0F9D3C7100292CCF /* MYCertificate.m in Sources */,
9.230 + 2706F1B10F9D3C7300292CCF /* MYCrypto+Cocoa.m in Sources */,
9.231 + 2706F1B40F9D3C7700292CCF /* MYDigest.m in Sources */,
9.232 + 2706F1B60F9D3C7800292CCF /* MYIdentity.m in Sources */,
9.233 + 2706F1B80F9D3C7A00292CCF /* MYKey.m in Sources */,
9.234 + 2706F1BA0F9D3C7D00292CCF /* MYKeychain.m in Sources */,
9.235 + 2706F1BC0F9D3C7E00292CCF /* MYKeychainItem.m in Sources */,
9.236 + 2706F1BE0F9D3C7F00292CCF /* MYPrivateKey.m in Sources */,
9.237 + 2706F1C00F9D3C8000292CCF /* MYPublicKey.m in Sources */,
9.238 + 2706F1C10F9D3C8100292CCF /* MYSymmetricKey-iPhone.m in Sources */,
9.239 + 2706F1C30F9D3C8300292CCF /* MYSymmetricKey.m in Sources */,
9.240 + 2706F1C50F9D3C8900292CCF /* MYCryptor.m in Sources */,
9.241 + 2706F1C70F9D3C8A00292CCF /* MYDecoder.m in Sources */,
9.242 + 2706F1C90F9D3C8B00292CCF /* MYEncoder.m in Sources */,
9.243 + 2706F1CB0F9D3C9300292CCF /* MYCertGen.m in Sources */,
9.244 + 27B852F70FCF4EB7005631F9 /* MYASN1Object.m in Sources */,
9.245 + 27B852FF0FCF4ECB005631F9 /* MYOID.m in Sources */,
9.246 + 27B855280FD077A7005631F9 /* MYDEREncoder.m in Sources */,
9.247 + 270A7A740FD58FF200770C4D /* MYBERParser.m in Sources */,
9.248 + );
9.249 + runOnlyForDeploymentPostprocessing = 0;
9.250 + };
9.251 8DD76F990486AA7600D96B5E /* Sources */ = {
9.252 isa = PBXSourcesBuildPhase;
9.253 buildActionMask = 2147483647;
9.254 @@ -325,6 +469,10 @@
9.255 27059D770F8FA23100A8422F /* MYCrypto+Cocoa.m in Sources */,
9.256 27059DE50F8FAF6500A8422F /* MYDecoder.m in Sources */,
9.257 27410FF00F99200A00AD413F /* MYSymmetricKey-iPhone.m in Sources */,
9.258 + 27B852F50FCF4EB7005631F9 /* MYASN1Object.m in Sources */,
9.259 + 27B853000FCF4ECB005631F9 /* MYOID.m in Sources */,
9.260 + 27B855290FD077A7005631F9 /* MYDEREncoder.m in Sources */,
9.261 + 270A7A750FD58FF200770C4D /* MYBERParser.m in Sources */,
9.262 );
9.263 runOnlyForDeploymentPostprocessing = 0;
9.264 };
9.265 @@ -368,6 +516,27 @@
9.266 };
9.267 name = Release;
9.268 };
9.269 + 2706F1AC0F9D3C6200292CCF /* Debug */ = {
9.270 + isa = XCBuildConfiguration;
9.271 + buildSettings = {
9.272 + ALWAYS_SEARCH_USER_PATHS = NO;
9.273 + COPY_PHASE_STRIP = NO;
9.274 + INSTALL_PATH = /usr/local/lib;
9.275 + PRODUCT_NAME = MYCrypto;
9.276 + };
9.277 + name = Debug;
9.278 + };
9.279 + 2706F1AD0F9D3C6200292CCF /* Release */ = {
9.280 + isa = XCBuildConfiguration;
9.281 + buildSettings = {
9.282 + ALWAYS_SEARCH_USER_PATHS = NO;
9.283 + COPY_PHASE_STRIP = YES;
9.284 + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
9.285 + INSTALL_PATH = /usr/local/lib;
9.286 + PRODUCT_NAME = MYCrypto;
9.287 + };
9.288 + name = Release;
9.289 + };
9.290 /* End XCBuildConfiguration section */
9.291
9.292 /* Begin XCConfigurationList section */
9.293 @@ -389,6 +558,15 @@
9.294 defaultConfigurationIsVisible = 0;
9.295 defaultConfigurationName = Release;
9.296 };
9.297 + 2706F1CE0F9D3CDD00292CCF /* Build configuration list for PBXNativeTarget "Static Lib" */ = {
9.298 + isa = XCConfigurationList;
9.299 + buildConfigurations = (
9.300 + 2706F1AC0F9D3C6200292CCF /* Debug */,
9.301 + 2706F1AD0F9D3C6200292CCF /* Release */,
9.302 + );
9.303 + defaultConfigurationIsVisible = 0;
9.304 + defaultConfigurationName = Release;
9.305 + };
9.306 /* End XCConfigurationList section */
9.307 };
9.308 rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
10.1 --- a/MYCryptoTest.m Sun Apr 19 22:05:51 2009 -0700
10.2 +++ b/MYCryptoTest.m Tue Jun 02 13:16:28 2009 -0700
10.3 @@ -155,7 +155,7 @@
10.4 #endif
10.5
10.6 #if !TARGET_OS_IPHONE
10.7 -#if 0 // TEMPORARILY OUT OF ORDER
10.8 +#if 1 // TEMP-ORARILY OUT OF ORDER
10.9 // Try exporting and importing a wrapped key:
10.10 Log(@"Testing export/import...");
10.11 NSData *exported = [key exportWrappedKeyWithPassphrasePrompt: @"Export symmetric key with passphrase:"];
10.12 @@ -163,14 +163,13 @@
10.13 #if 1
10.14 CAssert(exported);
10.15 #else
10.16 - //FIX: Exporting symmetric keys isn't working. Temporarily making this optional.
10.17 if (!exported)
10.18 Warn(@"Unable to export wrapped key");
10.19 else
10.20 #endif
10.21 {
10.22 CAssert(exported);
10.23 - MYSymmetricKey *key2 = [[MYSymmetricKey alloc] initWithKeyData: exported algorithm: algorithm];
10.24 + MYSymmetricKey *key2 = [[MYSymmetricKey alloc] initWithWrappedKeyData: exported];
10.25 Log(@"Reconstituted as %@", key2);
10.26 CAssertEqual(key2.keyData,key.keyData);
10.27 decrypted = [key2 decryptData: encrypted];
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/MYDEREncoder.h Tue Jun 02 13:16:28 2009 -0700
11.3 @@ -0,0 +1,25 @@
11.4 +//
11.5 +// MYDEREncoder.h
11.6 +// MYCrypto
11.7 +//
11.8 +// Created by Jens Alfke on 5/29/09.
11.9 +// Copyright 2009 Jens Alfke. All rights reserved.
11.10 +//
11.11 +
11.12 +#import <Foundation/Foundation.h>
11.13 +
11.14 +
11.15 +@interface MYDEREncoder : NSObject
11.16 +{
11.17 + id _rootObject;
11.18 + NSMutableData *_output;
11.19 + NSError *_error;
11.20 +}
11.21 +
11.22 +- (id) initWithRootObject: (id)object;
11.23 ++ (NSData*) encodeRootObject: (id)rootObject error: (NSError**)outError;
11.24 +
11.25 +@property (readonly) NSData* output;
11.26 +@property (readonly, retain) NSError *error;
11.27 +
11.28 +@end
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/MYDEREncoder.m Tue Jun 02 13:16:28 2009 -0700
12.3 @@ -0,0 +1,352 @@
12.4 +//
12.5 +// MYDEREncoder.m
12.6 +// MYCrypto
12.7 +//
12.8 +// Created by Jens Alfke on 5/29/09.
12.9 +// Copyright 2009 Jens Alfke. All rights reserved.
12.10 +//
12.11 +
12.12 +#import "MYDEREncoder.h"
12.13 +#import "MYASN1Object.h"
12.14 +#import "MYBERParser.h"
12.15 +#import "MYOID.h"
12.16 +#import "MYErrorUtils.h"
12.17 +
12.18 +
12.19 +#define MYDEREncoderException @"MYDEREncoderException"
12.20 +
12.21 +
12.22 +@interface MYDEREncoder ()
12.23 +- (void) _encode: (id)object;
12.24 +@property (retain) NSError *error;
12.25 +@end
12.26 +
12.27 +
12.28 +@implementation MYDEREncoder
12.29 +
12.30 +
12.31 +- (id) initWithRootObject: (id)rootObject
12.32 +{
12.33 + self = [super init];
12.34 + if (self != nil) {
12.35 + _rootObject = [rootObject retain];
12.36 + }
12.37 + return self;
12.38 +}
12.39 +
12.40 ++ (NSData*) encodeRootObject: (id)rootObject error: (NSError**)outError {
12.41 + MYDEREncoder *encoder = [[self alloc] initWithRootObject: rootObject];
12.42 + NSData *output = [encoder.output copy];
12.43 + if (outError) *outError = [[encoder.error retain] autorelease];
12.44 + [encoder release];
12.45 + return [output autorelease];
12.46 +}
12.47 +
12.48 +- (void) dealloc
12.49 +{
12.50 + [_rootObject release];
12.51 + [_output release];
12.52 + [super dealloc];
12.53 +}
12.54 +
12.55 +
12.56 +
12.57 +static unsigned sizeOfUnsignedInt (UInt64 n) {
12.58 + unsigned bytes = 0;
12.59 + for (; n; n >>= 8)
12.60 + bytes++;
12.61 + return bytes;
12.62 +}
12.63 +
12.64 +static unsigned encodeUnsignedInt (UInt64 n, UInt8 buf[], BOOL padHighBit) {
12.65 + unsigned size = MAX(1U, sizeOfUnsignedInt(n));
12.66 + UInt64 bigEndian = NSSwapHostLongLongToBig(n);
12.67 + const UInt8* src = (UInt8*)&bigEndian + (8-size);
12.68 + UInt8 *dst = &buf[0];
12.69 + if (padHighBit && (*src & 0x80)) {
12.70 + *dst++ = 0;
12.71 + size++;
12.72 + }
12.73 + memcpy(dst, src, size);
12.74 + return size;
12.75 +}
12.76 +
12.77 +static unsigned encodeSignedInt (SInt64 n, UInt8 buf[]) {
12.78 + if (n >= 0)
12.79 + return encodeUnsignedInt(n, buf, YES);
12.80 + else {
12.81 + unsigned size = MAX(1U, sizeOfUnsignedInt(~n));
12.82 + UInt64 bigEndian = NSSwapHostLongLongToBig(n);
12.83 + const UInt8* src = (UInt8*)&bigEndian + (8-size);
12.84 + UInt8 *dst = &buf[0];
12.85 + if (!(*src & 0x80)) {
12.86 + *dst++ = 0xFF;
12.87 + size++;
12.88 + }
12.89 + memcpy(dst, src, size);
12.90 + return size;
12.91 + }
12.92 +}
12.93 +
12.94 +
12.95 +- (void) _writeTag: (unsigned)tag
12.96 + class: (unsigned)tagClass
12.97 + constructed: (BOOL) constructed
12.98 + length: (size_t)length
12.99 +{
12.100 + struct {
12.101 + unsigned tag :5;
12.102 + unsigned isConstructed :1;
12.103 + unsigned tagClass :2;
12.104 + unsigned length :7;
12.105 + unsigned isLengthLong :1;
12.106 + UInt8 extraLength[9];
12.107 + } header;
12.108 + size_t headerSize = 2;
12.109 +
12.110 + header.tag = tag;
12.111 + header.isConstructed = constructed;
12.112 + header.tagClass = tagClass;
12.113 + if (length < 128) {
12.114 + header.isLengthLong = NO;
12.115 + header.length = length;
12.116 + } else {
12.117 + header.isLengthLong = YES;
12.118 + header.length = encodeUnsignedInt(length, header.extraLength, NO);
12.119 + headerSize += header.length;
12.120 + }
12.121 + [_output appendBytes: &header length: headerSize];
12.122 +}
12.123 +
12.124 +- (void) _writeTag: (unsigned)tag
12.125 + class: (unsigned)tagClass
12.126 + constructed: (BOOL) constructed
12.127 + bytes: (const void*)bytes
12.128 + length: (size_t)length
12.129 +{
12.130 + [self _writeTag: tag class: tagClass constructed: constructed length: length];
12.131 + [_output appendBytes: bytes length: length];
12.132 +}
12.133 +
12.134 +- (void) _writeTag: (unsigned)tag
12.135 + class: (unsigned)tagClass
12.136 + constructed: (BOOL) constructed
12.137 + data: (NSData*)data
12.138 +{
12.139 + Assert(data);
12.140 + [self _writeTag: tag class: tagClass constructed: constructed bytes: data.bytes length: data.length];
12.141 +}
12.142 +
12.143 +
12.144 +- (void) _encodeNumber: (NSNumber*)number {
12.145 + // Special-case detection of booleans by pointer equality, because otherwise they appear
12.146 + // identical to 0 and 1:
12.147 + if (number==$true || number==$false) {
12.148 + UInt8 value = number==$true ?0xFF :0x00;
12.149 + [self _writeTag: 1 class: 0 constructed: NO bytes: &value length: 1];
12.150 + return;
12.151 + }
12.152 +
12.153 + const char *type = number.objCType;
12.154 + if (strlen(type) == 1) {
12.155 + switch(type[0]) {
12.156 + case 'c':
12.157 + case 'i':
12.158 + case 's':
12.159 + case 'l':
12.160 + case 'q':
12.161 + { // Signed integers:
12.162 + UInt8 buf[9];
12.163 + size_t size = encodeSignedInt(number.longLongValue, buf);
12.164 + [self _writeTag: 2 class: 0 constructed: NO bytes: buf length: size];
12.165 + return;
12.166 + }
12.167 + case 'C':
12.168 + case 'I':
12.169 + case 'S':
12.170 + case 'L':
12.171 + case 'Q':
12.172 + { // Unsigned integers:
12.173 + UInt8 buf[9];
12.174 + size_t size = encodeUnsignedInt(number.unsignedLongLongValue, buf, YES);
12.175 + [self _writeTag: 2 class: 0 constructed: NO bytes: buf length: size];
12.176 + return;
12.177 + }
12.178 + case 'B':
12.179 + { // bool
12.180 + UInt8 value = number.boolValue ?0xFF :0x00;
12.181 + [self _writeTag: 1 class: 0 constructed: NO bytes: &value length: 1];
12.182 + return;
12.183 + }
12.184 + }
12.185 + }
12.186 + [NSException raise: MYDEREncoderException format: @"Can't DER-encode value %@ (typecode=%s)", number,type];
12.187 +}
12.188 +
12.189 +
12.190 +- (void) _encodeString: (NSString*)string {
12.191 + NSData *data = [string dataUsingEncoding: NSASCIIStringEncoding];
12.192 + if (data)
12.193 + [self _writeTag: 19 class: 0 constructed: NO data: data];
12.194 + else
12.195 + [self _writeTag: 12 class: 0 constructed: NO data: [string dataUsingEncoding: NSUTF8StringEncoding]];
12.196 +}
12.197 +
12.198 +
12.199 +- (void) _encodeBitString: (MYBitString*)bitString {
12.200 + NSUInteger bitCount = bitString.bitCount;
12.201 + [self _writeTag: 3 class: 0 constructed: NO length: 1 + (bitCount/8)];
12.202 + UInt8 unused = (8 - (bitCount % 8)) % 8;
12.203 + [_output appendBytes: &unused length: 1];
12.204 + [_output appendBytes: bitString.bits.bytes length: bitCount/8];
12.205 +}
12.206 +
12.207 +- (void) _encodeDate: (NSDate*)date {
12.208 + NSString *dateStr = [MYBERGeneralizedTimeFormatter() stringFromDate: date];
12.209 + Log(@"Encoded %@ as '%@'",date,dateStr);//TEMP
12.210 + [self _writeTag: 24 class: 0 constructed: NO data: [dateStr dataUsingEncoding: NSASCIIStringEncoding]];
12.211 +}
12.212 +
12.213 +
12.214 +- (void) _encodeCollection: (id)collection tag: (unsigned)tag class: (unsigned)tagClass {
12.215 + MYDEREncoder *subEncoder = [[[self class] alloc] init];
12.216 + for (id object in collection)
12.217 + [subEncoder _encode: object];
12.218 + [self _writeTag: tag class: tagClass constructed: YES data: subEncoder.output];
12.219 + [subEncoder release];
12.220 +}
12.221 +
12.222 +
12.223 +- (void) _encode: (id)object {
12.224 + if (!_output)
12.225 + _output = [[NSMutableData alloc] initWithCapacity: 1024];
12.226 + if ([object isKindOfClass: [NSNumber class]]) {
12.227 + [self _encodeNumber: object];
12.228 + } else if ([object isKindOfClass: [NSData class]]) {
12.229 + [self _writeTag: 4 class: 0 constructed: NO data: object];
12.230 + } else if ([object isKindOfClass: [MYBitString class]]) {
12.231 + [self _encodeBitString: object];
12.232 + } else if ([object isKindOfClass: [NSString class]]) {
12.233 + [self _encodeString: object];
12.234 + } else if ([object isKindOfClass: [NSDate class]]) {
12.235 + [self _encodeDate: object];
12.236 + } else if ([object isKindOfClass: [NSNull class]]) {
12.237 + [self _writeTag: 5 class: 0 constructed: NO bytes: NULL length: 0];
12.238 + } else if ([object isKindOfClass: [NSArray class]]) {
12.239 + [self _encodeCollection: object tag: 16 class: 0];
12.240 + } else if ([object isKindOfClass: [NSSet class]]) {
12.241 + [self _encodeCollection: object tag: 17 class: 0];
12.242 + } else if ([object isKindOfClass: [MYOID class]]) {
12.243 + [self _writeTag: 6 class: 0 constructed: NO data: [object DEREncoding]];
12.244 + } else if ([object isKindOfClass: [MYASN1Object class]]) {
12.245 + MYASN1Object *asn = object;
12.246 + if (asn.components)
12.247 + [self _encodeCollection: asn.components tag: asn.tag class: asn.tagClass];
12.248 + else
12.249 + [self _writeTag: asn.tag
12.250 + class: asn.tagClass
12.251 + constructed: asn.constructed
12.252 + data: asn.value];
12.253 + } else {
12.254 + [NSException raise: MYDEREncoderException format: @"Can't DER-encode a %@", [object class]];
12.255 + }
12.256 +}
12.257 +
12.258 +
12.259 +- (NSData*) output {
12.260 + if (!_output && !_error) {
12.261 + @try{
12.262 + [self _encode: _rootObject];
12.263 + }@catch (NSException *x) {
12.264 + if ($equal(x.name, MYDEREncoderException)) {
12.265 + self.error = MYError(2,MYASN1ErrorDomain, @"%@", x.reason);
12.266 + return nil;
12.267 + } else
12.268 + @throw(x);
12.269 + }
12.270 + }
12.271 + return _output;
12.272 +}
12.273 +
12.274 +@synthesize error=_error;
12.275 +
12.276 +
12.277 +@end
12.278 +
12.279 +
12.280 +
12.281 +#define $data(BYTES...) ({const uint8_t bytes[] = {BYTES}; [NSData dataWithBytes: bytes length: sizeof(bytes)];})
12.282 +
12.283 +TestCase(DEREncoder) {
12.284 + CAssertEqual([MYDEREncoder encodeRootObject: [NSNull null] error: nil],
12.285 + $data(0x05, 0x00));
12.286 + CAssertEqual([MYDEREncoder encodeRootObject: $true error: nil],
12.287 + $data(0x01, 0x01, 0xFF));
12.288 + CAssertEqual([MYDEREncoder encodeRootObject: $false error: nil],
12.289 + $data(0x01, 0x01, 0x00));
12.290 +
12.291 + // Integers:
12.292 + CAssertEqual([MYDEREncoder encodeRootObject: $object(0) error: nil],
12.293 + $data(0x02, 0x01, 0x00));
12.294 + CAssertEqual([MYDEREncoder encodeRootObject: $object(1) error: nil],
12.295 + $data(0x02, 0x01, 0x01));
12.296 + CAssertEqual([MYDEREncoder encodeRootObject: $object(-1) error: nil],
12.297 + $data(0x02, 0x01, 0xFF));
12.298 + CAssertEqual([MYDEREncoder encodeRootObject: $object(72) error: nil],
12.299 + $data(0x02, 0x01, 0x48));
12.300 + CAssertEqual([MYDEREncoder encodeRootObject: $object(-128) error: nil],
12.301 + $data(0x02, 0x01, 0x80));
12.302 + CAssertEqual([MYDEREncoder encodeRootObject: $object(128) error: nil],
12.303 + $data(0x02, 0x02, 0x00, 0x80));
12.304 + CAssertEqual([MYDEREncoder encodeRootObject: $object(255) error: nil],
12.305 + $data(0x02, 0x02, 0x00, 0xFF));
12.306 + CAssertEqual([MYDEREncoder encodeRootObject: $object(-256) error: nil],
12.307 + $data(0x02, 0x02, 0xFF, 0x00));
12.308 + CAssertEqual([MYDEREncoder encodeRootObject: $object(12345) error: nil],
12.309 + $data(0x02, 0x02, 0x30,0x39));
12.310 + CAssertEqual([MYDEREncoder encodeRootObject: $object(-12345) error: nil],
12.311 + $data(0x02, 0x02, 0xCF, 0xC7));
12.312 + CAssertEqual([MYDEREncoder encodeRootObject: $object(123456789) error: nil],
12.313 + $data(0x02, 0x04, 0x07, 0x5B, 0xCD, 0x15));
12.314 + CAssertEqual([MYDEREncoder encodeRootObject: $object(-123456789) error: nil],
12.315 + $data(0x02, 0x04, 0xF8, 0xA4, 0x32, 0xEB));
12.316 + CAssertEqual([MYDEREncoder encodeRootObject: $object(-123456789) error: nil],
12.317 + $data(0x02, 0x04, 0xF8, 0xA4, 0x32, 0xEB));
12.318 +
12.319 + // Strings:
12.320 + CAssertEqual([MYDEREncoder encodeRootObject: @"hello" error: nil],
12.321 + $data(0x13, 0x05, 'h', 'e', 'l', 'l', 'o'));
12.322 + CAssertEqual([MYDEREncoder encodeRootObject: @"thérè" error: nil],
12.323 + $data(0x0C, 0x07, 't', 'h', 0xC3, 0xA9, 'r', 0xC3, 0xA8));
12.324 +
12.325 + // Dates:
12.326 + CAssertEqual([MYDEREncoder encodeRootObject: [NSDate dateWithTimeIntervalSinceReferenceDate: 265336576]
12.327 + error: nil],
12.328 + $data(0x18, 0x0F, '2', '0', '0', '9', '0', '5', '3', '0', '0', '0', '3', '6', '1', '6', 'Z'));
12.329 +
12.330 + // Sequences:
12.331 + CAssertEqual([MYDEREncoder encodeRootObject: $array($object(72), $true) error: nil],
12.332 + $data(0x30, 0x06, 0x02, 0x01, 0x48, 0x01, 0x01, 0xFF));
12.333 + CAssertEqual([MYDEREncoder encodeRootObject: $array( $array($object(72), $true),
12.334 + $array($object(72), $true))
12.335 + error: nil],
12.336 + $data(0x30, 0x10,
12.337 + 0x30, 0x06, 0x02, 0x01, 0x48, 0x01, 0x01, 0xFF,
12.338 + 0x30, 0x06, 0x02, 0x01, 0x48, 0x01, 0x01, 0xFF));
12.339 +}
12.340 +
12.341 +
12.342 +TestCase(EncodeCert) {
12.343 + NSError *error = nil;
12.344 + NSData *cert = [NSData dataWithContentsOfFile: @"../../Tests/selfsigned.cer"]; //TEMP
12.345 + id certObjects = MYBERParse(cert,&error);
12.346 + CAssertNil(error);
12.347 + Log(@"Decoded as:\n%@", [MYASN1Object dump: certObjects]);
12.348 + NSData *encoded = [MYDEREncoder encodeRootObject: certObjects error: &error];
12.349 + CAssertNil(error);
12.350 + id reDecoded = MYBERParse(encoded, &error);
12.351 + CAssertNil(error);
12.352 + Log(@"Re-decoded as:\n%@", [MYASN1Object dump: reDecoded]);
12.353 + [encoded writeToFile: @"../../Tests/selfsigned_reencoded.cer" atomically: YES];
12.354 + CAssertEqual(encoded,cert);
12.355 +}
13.1 --- a/MYKey-iPhone.m Sun Apr 19 22:05:51 2009 -0700
13.2 +++ b/MYKey-iPhone.m Tue Jun 02 13:16:28 2009 -0700
13.3 @@ -59,6 +59,11 @@
13.4 return nil;
13.5 else
13.6 return [(id)CFMakeCollectable(data) autorelease];
13.7 +
13.8 + // The format of this data is not documented. There's been some reverse-engineering:
13.9 + // https://devforums.apple.com/message/32089#32089
13.10 + // Apparently it is a DER-formatted sequence of a modulus followed by an exponent.
13.11 + // This can be converted to OpenSSL format by wrapping it in some additional DER goop.
13.12 }
13.13
13.14
14.1 --- a/MYKeychain.h Sun Apr 19 22:05:51 2009 -0700
14.2 +++ b/MYKeychain.h Tue Jun 02 13:16:28 2009 -0700
14.3 @@ -102,6 +102,11 @@
14.4 //@{
14.5 #if !TARGET_OS_IPHONE
14.6
14.7 +/** Sets whether the keychain is allowed to pop up panels to interact with the user,
14.8 + for example to ask for permission to access keys. If user interaction is not
14.9 + allowed, all such requests will fail. */
14.10 ++ (void) setUserInteractionAllowed: (BOOL)allowed;
14.11 +
14.12 /** Enumerates all public keys in the keychain that have the given alias string. */
14.13 - (NSEnumerator*) symmetricKeysWithAlias: (NSString*)alias;
14.14
15.1 --- a/MYKeychain.m Sun Apr 19 22:05:51 2009 -0700
15.2 +++ b/MYKeychain.m Tue Jun 02 13:16:28 2009 -0700
15.3 @@ -206,6 +206,11 @@
15.4 }
15.5
15.6
15.7 ++ (void) setUserInteractionAllowed: (BOOL)allowed {
15.8 + SecKeychainSetUserInteractionAllowed(allowed);
15.9 +}
15.10 +
15.11 +
15.12 #pragma mark -
15.13 #pragma mark SEARCHING:
15.14
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/MYOID.h Tue Jun 02 13:16:28 2009 -0700
16.3 @@ -0,0 +1,25 @@
16.4 +//
16.5 +// MYOID.h
16.6 +// MYCrypto
16.7 +//
16.8 +// Created by Jens Alfke on 5/28/09.
16.9 +// Copyright 2009 Jens Alfke. All rights reserved.
16.10 +//
16.11 +
16.12 +#import <Cocoa/Cocoa.h>
16.13 +
16.14 +
16.15 +/** An ASN.1 Object-ID, which is a sequence of integer components that define namespaces. */
16.16 +@interface MYOID : NSObject <NSCopying>
16.17 +{
16.18 + NSData *_data;
16.19 +}
16.20 +
16.21 +- (id) initWithComponents: (const UInt32*)components count: (unsigned)componentCount;
16.22 +- (id) initWithBEREncoding: (NSData*)encoding;
16.23 +- (NSData*) DEREncoding;
16.24 +
16.25 +- (const UInt32*) components;
16.26 +- (unsigned) componentCount;
16.27 +
16.28 +@end
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
17.2 +++ b/MYOID.m Tue Jun 02 13:16:28 2009 -0700
17.3 @@ -0,0 +1,152 @@
17.4 +//
17.5 +// MYOID.m
17.6 +// MYCrypto
17.7 +//
17.8 +// Created by Jens Alfke on 5/28/09.
17.9 +// Copyright 2009 Jens Alfke. All rights reserved.
17.10 +//
17.11 +
17.12 +#import "MYOID.h"
17.13 +
17.14 +
17.15 +@implementation MYOID
17.16 +
17.17 +
17.18 +- (id) initWithComponents: (const UInt32*)components count: (unsigned)count
17.19 +{
17.20 + self = [super init];
17.21 + if (self != nil) {
17.22 + _data = [[NSData alloc] initWithBytes: components length: count*sizeof(UInt32)];
17.23 + }
17.24 + return self;
17.25 +}
17.26 +
17.27 +- (id) initWithBEREncoding: (NSData*)encoding
17.28 +{
17.29 + self = [super init];
17.30 + if (self != nil) {
17.31 + size_t len = encoding.length;
17.32 + const UInt8 *src = encoding.bytes;
17.33 + const UInt8 *end = src+len;
17.34 + NSMutableData *data = [NSMutableData dataWithLength: (len+1)*sizeof(UInt32)];
17.35 + UInt32* dst = data.mutableBytes;
17.36 +
17.37 + if (len >= 2) {
17.38 + *dst++ = *src / 40;
17.39 + *dst++ = *src % 40;
17.40 + src++;
17.41 + }
17.42 + while (src < end) {
17.43 + UInt32 component = 0;
17.44 + UInt8 byte;
17.45 + do{
17.46 + if (src >= end) {
17.47 + [self release];
17.48 + return nil;
17.49 + }
17.50 + byte = *src++;
17.51 + component = (component << 7) | (byte & 0x7F);
17.52 + }while (byte & 0x80);
17.53 + *dst++ = component;
17.54 + }
17.55 + data.length = (UInt8*)dst - (UInt8*)data.mutableBytes;
17.56 + _data = [data copy];
17.57 + }
17.58 + return self;
17.59 +}
17.60 +
17.61 ++ (MYOID*) OIDWithEncoding: (NSData*)encoding {
17.62 + return [[[self alloc] initWithBEREncoding: encoding] autorelease];
17.63 +}
17.64 +
17.65 +
17.66 +- (id) copyWithZone: (NSZone*)zone {
17.67 + return [self retain];
17.68 +}
17.69 +
17.70 +- (void) dealloc
17.71 +{
17.72 + [_data release];
17.73 + [super dealloc];
17.74 +}
17.75 +
17.76 +
17.77 +- (NSString*) description {
17.78 + NSMutableString *desc = [NSMutableString stringWithString: @"{"];
17.79 + const UInt32* components = self.components;
17.80 + unsigned count = self.componentCount;
17.81 + for (unsigned i=0; i<count; i++) {
17.82 + if (i>0)
17.83 + [desc appendString: @" "];
17.84 + [desc appendFormat: @"%u", components[i]];
17.85 + }
17.86 + [desc appendString: @"}"];
17.87 + return desc;
17.88 +}
17.89 +
17.90 +
17.91 +- (NSData*) componentData {return _data;}
17.92 +- (const UInt32*) components {return (const UInt32*)_data.bytes;}
17.93 +- (unsigned) componentCount {return _data.length / sizeof(UInt32);}
17.94 +
17.95 +- (NSUInteger)hash {
17.96 + return _data.hash;
17.97 +}
17.98 +
17.99 +- (BOOL)isEqual:(id)object {
17.100 + return [object isKindOfClass: [MYOID class]] && [_data isEqual: [object componentData]];
17.101 +}
17.102 +
17.103 +
17.104 +- (NSData*) DEREncoding {
17.105 + unsigned count = self.componentCount;
17.106 + UInt8 encoding[5*count]; // worst-case size
17.107 + const UInt32 *src=self.components, *end=src+count;
17.108 + UInt8 *dst = encoding;
17.109 + if (count >= 2 && src[0]<=3 && src[1]<40) {
17.110 + // Weird collapsing of 1st two components into one byte:
17.111 + *dst++ = src[0]*40 + src[1];
17.112 + src += 2;
17.113 + }
17.114 + while (src<end) {
17.115 + UInt32 component = *src++;
17.116 + // Write the component in 7-bit groups, most significant first:
17.117 + BOOL any = NO;
17.118 + for (int shift=28; shift>=0; shift -= 7) {
17.119 + UInt8 byte = (component >> shift) & 0x7F;
17.120 + if (byte || any) {
17.121 + if (any)
17.122 + dst[-1] |= 0x80;
17.123 + *dst++ = byte;
17.124 + any = YES;
17.125 + }
17.126 + }
17.127 + }
17.128 + return [NSData dataWithBytes: encoding length: dst-encoding];
17.129 +}
17.130 +
17.131 +
17.132 +@end
17.133 +
17.134 +
17.135 +
17.136 +#define $data(BYTES...) ({const uint8_t bytes[] = {BYTES}; [NSData dataWithBytes: bytes length: sizeof(bytes)];})
17.137 +
17.138 +#define $components(INTS...) ({const UInt32 components[] = {INTS}; components;})
17.139 +
17.140 +TestCase(OID) {
17.141 + CAssertEqual([[MYOID OIDWithEncoding: $data(0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01)] description],
17.142 + @"{1 2 840 113549 1 1 1}");
17.143 + CAssertEqual([[MYOID OIDWithEncoding: $data(0x55,0x04,0x04)] description],
17.144 + @"{2 5 4 4}");
17.145 + CAssertEqual([[MYOID OIDWithEncoding: $data(0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x09,0x01)] description],
17.146 + @"{1 2 840 113549 1 9 1}");
17.147 +
17.148 + CAssertEqual([[[MYOID alloc] initWithComponents: $components(1,2,840,113549,1,1,1) count: 7] description],
17.149 + @"{1 2 840 113549 1 1 1}");
17.150 +
17.151 + CAssertEqual([[[MYOID alloc] initWithComponents: $components(1,2,840,113549,1,1,1) count: 7] DEREncoding],
17.152 + $data(0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01));
17.153 + CAssertEqual([[[MYOID alloc] initWithComponents: $components(2,5,4,4) count: 4] DEREncoding],
17.154 + $data(0x55,0x04,0x04));
17.155 +}
18.1 --- a/MYSymmetricKey.h Sun Apr 19 22:05:51 2009 -0700
18.2 +++ b/MYSymmetricKey.h Tue Jun 02 13:16:28 2009 -0700
18.3 @@ -10,8 +10,17 @@
18.4 #import <CommonCrypto/CommonCryptor.h>
18.5
18.6
18.7 +/** An old-fashioned symmetric key, so named because it both encrypts and decrypts.
18.8 + A key can be generated at random, stored in the keychain, or derived from a user-entered
18.9 + passphrase.
18.10 +
18.11 + These days, symmetric encryption is used mostly on local data such as files, with
18.12 + passphrases; or as a transient "session key" for data sent between users, with the
18.13 + session key itself encrypted in the message using public-key encryption. (The
18.14 + MYEncoder/MYDecoder classes manage this second usage, whose details are tricky.) */
18.15 @interface MYSymmetricKey : MYKey <MYEncryption, MYDecryption>
18.16 {
18.17 + @private
18.18 #if !MYCRYPTO_USE_IPHONE_API
18.19 CSSM_KEY *_ownedCSSMKey;
18.20 #endif
18.21 @@ -36,7 +45,17 @@
18.22
18.23 #if !TARGET_OS_IPHONE
18.24
18.25 -- (NSData*) exportWrappedKeyWithPassphrasePrompt: (NSString*)prompt;
18.26 +/** Exports the key as a data blob, so that it can be stored as a backup, or transferred
18.27 + to another computer. Since the key is sensitive, it must be exported in encrypted form
18.28 + using a user-chosen passphrase. This method will display a standard alert panel, run by
18.29 + the Security agent, that prompts the user to enter a new passphrase for encrypting the key.
18.30 + The same passphrase must be re-entered when importing the key from the data blob. */
18.31 + - (NSData*) exportWrappedKeyWithPassphrasePrompt: (NSString*)prompt;
18.32 +
18.33 +/** Recreates a symmetric key from its wrapped (encrypted) form. The user will be prompted for
18.34 + the passphrase to decrypt the key; this must be the same passphrase that was entered when
18.35 + wrapping the key, e.g. when -exportWrappedKeyWithPassphrasePrompt: was called. */
18.36 +- (id) initWithWrappedKeyData: (NSData*)wrappedKeyData;
18.37
18.38 /** Converts a passphrase into a symmetric key.
18.39 The same passphrase (and salt) will always return the same key, so you can use this method
18.40 @@ -48,12 +67,12 @@
18.41 passphrase twice, to check for errors, and the nifty passphrase-strength meter will be
18.42 displayed. If NO, there's only one text-field, and an option to display its contents in
18.43 the clear.
18.44 - @param salt An arbitrary value whose data will be mixed in with the passphrase before
18.45 + @param saltObj An arbitrary value whose data will be mixed in with the passphrase before
18.46 hashing, to perturb the resulting bits. The purpose of this is to make it harder for
18.47 an attacker to brute-force the key using a precompiled list of digests of common
18.48 passwords. Changing the salt changes the key, so you need to pass the same value when
18.49 re-deriving the key as you did when first generating it. */
18.50 - + (MYSymmetricKey*) generateFromUserPassphraseWithAlertTitle: (NSString*)alertTitle
18.51 ++ (MYSymmetricKey*) generateFromUserPassphraseWithAlertTitle: (NSString*)alertTitle
18.52 alertPrompt: (NSString*)prompt
18.53 creating: (BOOL)creating
18.54 salt: (id)saltObj;
19.1 --- a/MYSymmetricKey.m Sun Apr 19 22:05:51 2009 -0700
19.2 +++ b/MYSymmetricKey.m Tue Jun 02 13:16:28 2009 -0700
19.3 @@ -34,8 +34,15 @@
19.4
19.5 static CSSM_KEY* cssmKeyFromData( NSData *keyData, CSSM_ALGORITHMS algorithm,
19.6 MYKeychain *keychain);
19.7 -//static CSSM_ENCRYPT_MODE defaultModeForAlgorithm(CSSM_ALGORITHMS algorithm);
19.8 -//CSSM_PADDING defaultPaddingForAlgorithm(CSSM_ALGORITHMS algorithm);
19.9 +
19.10 +#if !TARGET_OS_IPHONE
19.11 +static CSSM_KEY* unwrapCssmKeyFromData(NSData *wrappedData,
19.12 + CSSM_ALGORITHMS algorithm,
19.13 + unsigned sizeInBits);
19.14 +static CSSM_ENCRYPT_MODE defaultModeForAlgorithm(CSSM_ALGORITHMS algorithm);
19.15 +static CSSM_PADDING defaultPaddingForAlgorithm(CSSM_ALGORITHMS algorithm);
19.16 +#endif
19.17 +
19.18 static CSSM_DATA makeSalt( id salty, size_t length );
19.19 static CSSM_RETURN impExpCreatePassKey(
19.20 const SecKeyImportExportParameters *keyParams, // required
19.21 @@ -49,6 +56,10 @@
19.22
19.23
19.24 - (id) _initWithCSSMKey: (CSSM_KEY*)cssmKey {
19.25 + if (!cssmKey) {
19.26 + [self release];
19.27 + return nil;
19.28 + }
19.29 SecKeyRef keyRef = NULL;
19.30 if (SecKeyCreate == NULL) {
19.31 // If weak-linked SPI fn no longer exists
19.32 @@ -75,10 +86,6 @@
19.33 Assert(algorithm <= kCCAlgorithmRC4);
19.34 Assert(keyData);
19.35 CSSM_KEY *key = cssmKeyFromData(keyData, CSSMFromCCAlgorithm(algorithm), keychain);
19.36 - if (!key) {
19.37 - [self release];
19.38 - return nil;
19.39 - }
19.40 return [self _initWithCSSMKey: key];
19.41 }
19.42
19.43 @@ -223,9 +230,15 @@
19.44
19.45
19.46 #if !TARGET_OS_IPHONE
19.47 +- (id) initWithWrappedKeyData: (NSData*)wrappedKeyData {
19.48 + return [self _initWithCSSMKey: unwrapCssmKeyFromData(wrappedKeyData,
19.49 + CSSM_ALGID_AES,128)];
19.50 +}
19.51 +
19.52 +
19.53 - (NSData*) exportWrappedKeyWithPassphrasePrompt: (NSString*)prompt
19.54 {
19.55 - // Prompt use for a passphrase to use for the wrapping key:
19.56 + // Prompt user for a passphrase to use for the wrapping key:
19.57 MYSymmetricKey *wrappingKey = [MYSymmetricKey
19.58 generateFromUserPassphraseWithAlertTitle: @"Export Key"
19.59 alertPrompt: prompt
19.60 @@ -238,15 +251,17 @@
19.61 // Create the context:
19.62 CSSM_ACCESS_CREDENTIALS credentials = {};
19.63 CSSM_CSP_HANDLE cspHandle = self.cssmCSPHandle;
19.64 - //CSSM_ALGORITHMS algorithm = wrappingKey.cssmAlgorithm;
19.65 + CSSM_ALGORITHMS algorithm = wrappingKey.cssmAlgorithm;
19.66 + uint8 iv[16] = {0}; // Right size for AES. Are zeros OK? //FIX: Support other algorithms
19.67 + CSSM_DATA ivData = {.Data=(void*)&iv, .Length=sizeof(iv)};
19.68 CSSM_CC_HANDLE ctx;
19.69 if (!checkcssm(CSSM_CSP_CreateSymmetricContext(cspHandle,
19.70 - wrappingKey.cssmAlgorithm, //CSSM_ALGID_3DES_3KEY_EDE, //algorithm,
19.71 - CSSM_ALGMODE_CBCPadIV8, //defaultModeForAlgorithm(algorithm),
19.72 + algorithm, //CSSM_ALGID_3DES_3KEY_EDE
19.73 + defaultModeForAlgorithm(algorithm),
19.74 &credentials,
19.75 wrappingKey.cssmKey,
19.76 - NULL,
19.77 - CSSM_PADDING_PKCS7, //defaultPaddingForAlgorithm(algorithm),
19.78 + &ivData,
19.79 + defaultPaddingForAlgorithm(algorithm),
19.80 NULL,
19.81 &ctx),
19.82 @"CSSM_CSP_CreateSymmetricContext"))
19.83 @@ -396,6 +411,35 @@
19.84 }
19.85
19.86
19.87 +#if !TARGET_OS_IPHONE
19.88 +static CSSM_KEY* unwrapCssmKeyFromData(NSData *wrappedData,
19.89 + CSSM_ALGORITHMS algorithm,
19.90 + unsigned sizeInBits) {
19.91 + Warn(@"MYSymmetricKey: unwrapping is unimplemented; sorry");
19.92 + return nil;
19.93 +#if 0 //not finished yet
19.94 + // First create a wrapped-key structure from the data:
19.95 + CSSM_WRAP_KEY wrappedKey = {
19.96 + .KeyHeader = {
19.97 + .BlobType = CSSM_KEYBLOB_WRAPPED,
19.98 + .Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS3,
19.99 + .AlgorithmId = algorithm,
19.100 + .KeyClass = CSSM_KEYCLASS_SESSION_KEY,
19.101 + .LogicalKeySizeInBits = sizeInBits,
19.102 + .KeyAttr = CSSM_KEYATTR_EXTRACTABLE,
19.103 + .KeyUsage = CSSM_KEYUSE_ANY,
19.104 + .WrapAlgorithmId = CSSM_ALGID_AES,
19.105 + },
19.106 + .KeyData = {
19.107 + .Data = (void*)wrappedData.bytes,
19.108 + .Length = wrappedData.length
19.109 + }
19.110 + };
19.111 +#endif
19.112 +}
19.113 +#endif
19.114 +
19.115 +
19.116 // Create salt data of a specific length from an arbitrary NSObject. */
19.117 static CSSM_DATA makeSalt( id salty, size_t length ) {
19.118 // Convert to NSData if necessary:
19.119 @@ -416,7 +460,9 @@
19.120
19.121 #pragma mark -
19.122 // Code from Keychain.framework:
19.123 -#if 0
19.124 +
19.125 +#if !TARGET_OS_IPHONE
19.126 +#if 1
19.127 static CSSM_ENCRYPT_MODE defaultModeForAlgorithm(CSSM_ALGORITHMS algorithm) {
19.128 switch(algorithm) {
19.129 // 8-byte block ciphers
19.130 @@ -438,8 +484,10 @@
19.131 return CSSM_ALGMODE_NONE;
19.132 }
19.133 }
19.134 +#endif
19.135
19.136 -CSSM_PADDING defaultPaddingForAlgorithm(CSSM_ALGORITHMS algorithm) {
19.137 +#if 1
19.138 +static CSSM_PADDING defaultPaddingForAlgorithm(CSSM_ALGORITHMS algorithm) {
19.139 switch(algorithm) {
19.140 /* 8-byte block ciphers */
19.141 case CSSM_ALGID_DES:
19.142 @@ -465,6 +513,7 @@
19.143 }
19.144 }
19.145 #endif
19.146 +#endif
19.147
19.148 #pragma mark -
19.149 // Code below was copied from SecImportExportUtils.cpp in Apple's libsecurity_keychain project
20.1 Binary file Tests/iphonedev.cer has changed
21.1 Binary file Tests/selfsigned.cer has changed