jens@16: // jens@16: // MYOID.m jens@16: // MYCrypto jens@16: // jens@16: // Created by Jens Alfke on 5/28/09. jens@16: // Copyright 2009 Jens Alfke. All rights reserved. jens@16: // jens@16: jens@16: #import "MYOID.h" jens@16: jens@16: jens@16: @implementation MYOID jens@16: jens@16: jens@16: - (id) initWithComponents: (const UInt32*)components count: (unsigned)count jens@16: { jens@16: self = [super init]; jens@16: if (self != nil) { jens@16: _data = [[NSData alloc] initWithBytes: components length: count*sizeof(UInt32)]; jens@16: } jens@16: return self; jens@16: } jens@16: jens@16: - (id) initWithBEREncoding: (NSData*)encoding jens@16: { jens@16: self = [super init]; jens@16: if (self != nil) { jens@16: size_t len = encoding.length; jens@16: const UInt8 *src = encoding.bytes; jens@16: const UInt8 *end = src+len; jens@16: NSMutableData *data = [NSMutableData dataWithLength: (len+1)*sizeof(UInt32)]; jens@16: UInt32* dst = data.mutableBytes; jens@16: jens@16: if (len >= 2) { jens@16: *dst++ = *src / 40; jens@16: *dst++ = *src % 40; jens@16: src++; jens@16: } jens@16: while (src < end) { jens@16: UInt32 component = 0; jens@16: UInt8 byte; jens@16: do{ jens@16: if (src >= end) { jens@16: [self release]; jens@16: return nil; jens@16: } jens@16: byte = *src++; jens@16: component = (component << 7) | (byte & 0x7F); jens@16: }while (byte & 0x80); jens@16: *dst++ = component; jens@16: } jens@16: data.length = (UInt8*)dst - (UInt8*)data.mutableBytes; jens@16: _data = [data copy]; jens@16: } jens@16: return self; jens@16: } jens@16: jens@16: + (MYOID*) OIDWithEncoding: (NSData*)encoding { jens@16: return [[[self alloc] initWithBEREncoding: encoding] autorelease]; jens@16: } jens@16: jens@28: #if !TARGET_OS_IPHONE jens@26: + (MYOID*) OIDFromCSSM: (CSSM_OID)cssmOid jens@26: { jens@26: NSData *ber = [[NSData alloc] initWithBytesNoCopy: cssmOid.Data length: cssmOid.Length freeWhenDone: NO]; jens@26: MYOID *oid = [[[self alloc] initWithBEREncoding: ber] autorelease]; jens@26: [ber release]; jens@26: return oid; jens@26: } jens@26: #endif jens@26: jens@16: jens@16: - (id) copyWithZone: (NSZone*)zone { jens@16: return [self retain]; jens@16: } jens@16: jens@16: - (void) dealloc jens@16: { jens@16: [_data release]; jens@16: [super dealloc]; jens@16: } jens@16: jens@16: jens@16: - (NSString*) description { jens@16: NSMutableString *desc = [NSMutableString stringWithString: @"{"]; jens@16: const UInt32* components = self.components; jens@16: unsigned count = self.componentCount; jens@16: for (unsigned i=0; i0) jens@16: [desc appendString: @" "]; jens@16: [desc appendFormat: @"%u", components[i]]; jens@16: } jens@16: [desc appendString: @"}"]; jens@16: return desc; jens@16: } jens@16: jens@16: jens@16: - (NSData*) componentData {return _data;} jens@16: - (const UInt32*) components {return (const UInt32*)_data.bytes;} jens@16: - (unsigned) componentCount {return _data.length / sizeof(UInt32);} jens@16: jens@16: - (NSUInteger)hash { jens@16: return _data.hash; jens@16: } jens@16: jens@16: - (BOOL)isEqual:(id)object { jens@16: return [object isKindOfClass: [MYOID class]] && [_data isEqual: [object componentData]]; jens@16: } jens@16: jens@16: jens@16: - (NSData*) DEREncoding { jens@16: unsigned count = self.componentCount; jens@16: UInt8 encoding[5*count]; // worst-case size jens@16: const UInt32 *src=self.components, *end=src+count; jens@16: UInt8 *dst = encoding; jens@16: if (count >= 2 && src[0]<=3 && src[1]<40) { jens@16: // Weird collapsing of 1st two components into one byte: jens@16: *dst++ = src[0]*40 + src[1]; jens@16: src += 2; jens@16: } jens@16: while (src=0; shift -= 7) { jens@16: UInt8 byte = (component >> shift) & 0x7F; jens@16: if (byte || any) { jens@16: if (any) jens@16: dst[-1] |= 0x80; jens@16: *dst++ = byte; jens@16: any = YES; jens@16: } jens@16: } jens@16: } jens@16: return [NSData dataWithBytes: encoding length: dst-encoding]; jens@16: } jens@16: jens@16: jens@16: @end jens@16: jens@16: jens@16: jens@16: #define $data(BYTES...) ({const uint8_t bytes[] = {BYTES}; [NSData dataWithBytes: bytes length: sizeof(bytes)];}) jens@16: jens@16: #define $components(INTS...) ({const UInt32 components[] = {INTS}; components;}) jens@16: jens@16: TestCase(OID) { jens@16: CAssertEqual([[MYOID OIDWithEncoding: $data(0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01)] description], jens@16: @"{1 2 840 113549 1 1 1}"); jens@16: CAssertEqual([[MYOID OIDWithEncoding: $data(0x55,0x04,0x04)] description], jens@16: @"{2 5 4 4}"); jens@16: CAssertEqual([[MYOID OIDWithEncoding: $data(0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x09,0x01)] description], jens@16: @"{1 2 840 113549 1 9 1}"); jens@16: jens@16: CAssertEqual([[[MYOID alloc] initWithComponents: $components(1,2,840,113549,1,1,1) count: 7] description], jens@16: @"{1 2 840 113549 1 1 1}"); jens@16: jens@16: CAssertEqual([[[MYOID alloc] initWithComponents: $components(1,2,840,113549,1,1,1) count: 7] DEREncoding], jens@16: $data(0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01)); jens@16: CAssertEqual([[[MYOID alloc] initWithComponents: $components(2,5,4,4) count: 4] DEREncoding], jens@16: $data(0x55,0x04,0x04)); jens@16: } jens@21: jens@21: jens@21: jens@21: /* jens@21: Copyright (c) 2009, Jens Alfke . All rights reserved. jens@21: jens@21: Redistribution and use in source and binary forms, with or without modification, are permitted jens@21: provided that the following conditions are met: jens@21: jens@21: * Redistributions of source code must retain the above copyright notice, this list of conditions jens@21: and the following disclaimer. jens@21: * Redistributions in binary form must reproduce the above copyright notice, this list of conditions jens@21: and the following disclaimer in the documentation and/or other materials provided with the jens@21: distribution. jens@21: jens@21: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR jens@21: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND jens@21: FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI- jens@21: BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES jens@21: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR jens@21: PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN jens@21: CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF jens@21: THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. jens@21: */