MYOID.m
author Jens Alfke <jens@mooseyard.com>
Wed Jun 10 09:02:18 2009 -0700 (2009-06-10)
changeset 25 38c3c3923e1f
parent 16 c409dbc4f068
child 26 d9c2a06d4e4e
permissions -rw-r--r--
Changed the X.509 version number in generated certs from 1 to 3, so that SecCertificateCreateFromData on iPhone will accept them. :-/
     1 //
     2 //  MYOID.m
     3 //  MYCrypto
     4 //
     5 //  Created by Jens Alfke on 5/28/09.
     6 //  Copyright 2009 Jens Alfke. All rights reserved.
     7 //
     8 
     9 #import "MYOID.h"
    10 
    11 
    12 @implementation MYOID
    13 
    14 
    15 - (id) initWithComponents: (const UInt32*)components count: (unsigned)count
    16 {
    17     self = [super init];
    18     if (self != nil) {
    19         _data = [[NSData alloc] initWithBytes: components length: count*sizeof(UInt32)];
    20     }
    21     return self;
    22 }
    23 
    24 - (id) initWithBEREncoding: (NSData*)encoding
    25 {
    26     self = [super init];
    27     if (self != nil) {
    28         size_t len = encoding.length;
    29         const UInt8 *src = encoding.bytes;
    30         const UInt8 *end = src+len;
    31         NSMutableData *data = [NSMutableData dataWithLength: (len+1)*sizeof(UInt32)];
    32         UInt32* dst = data.mutableBytes;
    33         
    34         if (len >= 2) {
    35             *dst++ = *src / 40;
    36             *dst++ = *src % 40;
    37             src++; 
    38         }
    39         while (src < end) {
    40             UInt32 component = 0;
    41             UInt8 byte;
    42             do{
    43                 if (src >= end) {
    44                     [self release];
    45                     return nil;
    46                 }
    47                 byte = *src++;
    48                 component = (component << 7) | (byte & 0x7F);
    49             }while (byte & 0x80);
    50             *dst++ = component;
    51         }
    52         data.length = (UInt8*)dst - (UInt8*)data.mutableBytes;
    53         _data = [data copy];
    54     }
    55     return self;
    56 }
    57 
    58 + (MYOID*) OIDWithEncoding: (NSData*)encoding {
    59     return [[[self alloc] initWithBEREncoding: encoding] autorelease];
    60 }
    61 
    62 
    63 - (id) copyWithZone: (NSZone*)zone {
    64     return [self retain];
    65 }
    66 
    67 - (void) dealloc
    68 {
    69     [_data release];
    70     [super dealloc];
    71 }
    72 
    73 
    74 - (NSString*) description {
    75     NSMutableString *desc = [NSMutableString stringWithString: @"{"];
    76     const UInt32* components = self.components;
    77     unsigned count = self.componentCount;
    78     for (unsigned i=0; i<count; i++) {
    79         if (i>0)
    80             [desc appendString: @" "];
    81         [desc appendFormat: @"%u", components[i]];
    82     }
    83     [desc appendString: @"}"];
    84     return desc;
    85 }
    86 
    87 
    88 - (NSData*) componentData       {return _data;}
    89 - (const UInt32*) components    {return (const UInt32*)_data.bytes;}
    90 - (unsigned) componentCount     {return _data.length / sizeof(UInt32);}
    91 
    92 - (NSUInteger)hash {
    93     return _data.hash;
    94 }
    95 
    96 - (BOOL)isEqual:(id)object {
    97     return [object isKindOfClass: [MYOID class]] && [_data isEqual: [object componentData]];
    98 }
    99 
   100 
   101 - (NSData*) DEREncoding {
   102     unsigned count = self.componentCount;
   103     UInt8 encoding[5*count]; // worst-case size
   104     const UInt32 *src=self.components, *end=src+count;
   105     UInt8 *dst = encoding;
   106     if (count >= 2 && src[0]<=3 && src[1]<40) {
   107         // Weird collapsing of 1st two components into one byte:
   108         *dst++ = src[0]*40 + src[1];
   109         src += 2;
   110     }
   111     while (src<end) {
   112         UInt32 component = *src++;
   113         // Write the component in 7-bit groups, most significant first:
   114         BOOL any = NO;
   115         for (int shift=28; shift>=0; shift -= 7) {
   116             UInt8 byte = (component >> shift) & 0x7F;
   117             if (byte || any) {
   118                 if (any)
   119                     dst[-1] |= 0x80;
   120                 *dst++ = byte;
   121                 any = YES;
   122             }
   123         }
   124     }
   125     return [NSData dataWithBytes: encoding length: dst-encoding];
   126 }
   127 
   128 
   129 @end
   130 
   131 
   132 
   133 #define $data(BYTES...)    ({const uint8_t bytes[] = {BYTES}; [NSData dataWithBytes: bytes length: sizeof(bytes)];})
   134 
   135 #define $components(INTS...)    ({const UInt32 components[] = {INTS}; components;})
   136 
   137 TestCase(OID) {
   138     CAssertEqual([[MYOID OIDWithEncoding: $data(0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01)] description],
   139                  @"{1 2 840 113549 1 1 1}");
   140     CAssertEqual([[MYOID OIDWithEncoding: $data(0x55,0x04,0x04)] description],
   141                  @"{2 5 4 4}");
   142     CAssertEqual([[MYOID OIDWithEncoding: $data(0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x09,0x01)] description],
   143                  @"{1 2 840 113549 1 9 1}");
   144 
   145     CAssertEqual([[[MYOID alloc] initWithComponents: $components(1,2,840,113549,1,1,1) count: 7] description],
   146                  @"{1 2 840 113549 1 1 1}");
   147 
   148     CAssertEqual([[[MYOID alloc] initWithComponents: $components(1,2,840,113549,1,1,1) count: 7] DEREncoding],
   149                  $data(0x2a, 0x86, 0x48, 0x86,  0xf7, 0x0d, 0x01, 0x01,  0x01));
   150     CAssertEqual([[[MYOID alloc] initWithComponents: $components(2,5,4,4) count: 4] DEREncoding],
   151                  $data(0x55,0x04,0x04));
   152 }
   153 
   154 
   155 
   156 /*
   157  Copyright (c) 2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
   158  
   159  Redistribution and use in source and binary forms, with or without modification, are permitted
   160  provided that the following conditions are met:
   161  
   162  * Redistributions of source code must retain the above copyright notice, this list of conditions
   163  and the following disclaimer.
   164  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
   165  and the following disclaimer in the documentation and/or other materials provided with the
   166  distribution.
   167  
   168  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
   169  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
   170  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
   171  BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   172  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
   173   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   174  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
   175  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   176  */