MYBERParser.m
changeset 17 90a70925562b
parent 16 c409dbc4f068
child 19 f6c91b9da05b
     1.1 --- a/MYBERParser.m	Tue Jun 02 13:16:28 2009 -0700
     1.2 +++ b/MYBERParser.m	Wed Jun 03 17:20:53 2009 -0700
     1.3 @@ -19,6 +19,14 @@
     1.4  
     1.5  
     1.6  typedef struct {
     1.7 +    unsigned tag            :5;
     1.8 +    unsigned isConstructed  :1;
     1.9 +    unsigned tagClass       :2;
    1.10 +    unsigned length         :7;
    1.11 +    unsigned isLengthLong   :1;
    1.12 +} BERHeader;
    1.13 +
    1.14 +typedef struct {
    1.15      const uint8_t *nextChar;
    1.16      size_t length;
    1.17  } InputData;
    1.18 @@ -103,27 +111,23 @@
    1.19  }
    1.20  
    1.21  
    1.22 +static size_t readHeader(InputData *input, BERHeader *header) {
    1.23 +    memcpy(header, readOrDie(input,2), 2);
    1.24 +    if (header->tag == 0x1F)
    1.25 +        [NSException raise: MYBERParserException format: @"Long tags not supported"];
    1.26 +    if (!header->isLengthLong)
    1.27 +        return header->length;
    1.28 +    else {
    1.29 +        if (header->length == 0)
    1.30 +            [NSException raise: MYBERParserException format: @"Indefinite length not supported"];
    1.31 +        return NSSwapBigIntToHost(readBigEndianUnsignedInteger(input,header->length));
    1.32 +    }
    1.33 +}
    1.34 +
    1.35 +
    1.36  static id parseBER(InputData *input) {
    1.37 -    struct {
    1.38 -        unsigned tag            :5;
    1.39 -        unsigned isConstructed  :1;
    1.40 -        unsigned tagClass       :2;
    1.41 -        unsigned length         :7;
    1.42 -        unsigned isLengthLong   :1;
    1.43 -    } header;
    1.44 -    memcpy(&header, readOrDie(input,2), 2);
    1.45 -    
    1.46 -    if (header.tag == 0x1F)
    1.47 -        [NSException raise: MYBERParserException format: @"Long tags not supported"];
    1.48 -    
    1.49 -    // Parse the length:
    1.50 -    size_t length;
    1.51 -    if (!header.isLengthLong)
    1.52 -        length = header.length;
    1.53 -    else if (header.length == 0)
    1.54 -        [NSException raise: MYBERParserException format: @"Indefinite length not supported"];
    1.55 -    else
    1.56 -        length = NSSwapBigIntToHost(readBigEndianUnsignedInteger(input,header.length));
    1.57 +    BERHeader header;
    1.58 +    size_t length = readHeader(input,&header);
    1.59      
    1.60      Class defaultClass = [MYASN1Object class];
    1.61      
    1.62 @@ -209,6 +213,16 @@
    1.63          Warn(@"parseBER: Returning default %@", result);
    1.64      return result;
    1.65  }
    1.66 +    
    1.67 +    
    1.68 +static void exceptionToError (NSException *x, NSError **outError) {
    1.69 +    if ($equal(x.name, MYBERParserException)) {
    1.70 +        if (outError)
    1.71 +            *outError = MYError(1,MYASN1ErrorDomain, @"%@", x.reason);
    1.72 +    } else {
    1.73 +        @throw(x);
    1.74 +    }
    1.75 +}
    1.76  
    1.77  
    1.78  id MYBERParse (NSData *ber, NSError **outError) {
    1.79 @@ -216,16 +230,35 @@
    1.80          InputData input = {ber.bytes, ber.length};
    1.81          return parseBER(&input);
    1.82      }@catch (NSException *x) {
    1.83 -        if ($equal(x.name, MYBERParserException)) {
    1.84 -            *outError = MYError(1,MYASN1ErrorDomain, @"%@", x.reason);
    1.85 -        } else {
    1.86 -            @throw(x);
    1.87 -        }
    1.88 +        exceptionToError(x,outError);
    1.89      }
    1.90      return nil;
    1.91  }
    1.92  
    1.93  
    1.94 +size_t MYBERGetLength (NSData *ber, NSError **outError) {
    1.95 +    @try{
    1.96 +        InputData input = {ber.bytes, ber.length};
    1.97 +        BERHeader header;
    1.98 +        return readHeader(&input,&header);
    1.99 +    }@catch (NSException *x) {
   1.100 +        exceptionToError(x,outError);
   1.101 +    }
   1.102 +    return 0;
   1.103 +}
   1.104 +
   1.105 +const void* MYBERGetContents (NSData *ber, NSError **outError) {
   1.106 +    @try{
   1.107 +        InputData input = {ber.bytes, ber.length};
   1.108 +        BERHeader header;
   1.109 +        readHeader(&input,&header);
   1.110 +        return input.nextChar;
   1.111 +    }@catch (NSException *x) {
   1.112 +        exceptionToError(x,outError);
   1.113 +    }
   1.114 +    return NULL;
   1.115 +}
   1.116 +
   1.117  
   1.118  
   1.119  #pragma mark -
   1.120 @@ -280,6 +313,9 @@
   1.121  }
   1.122  
   1.123  
   1.124 +#import "MYCertificate.h"
   1.125 +#import "MYPublicKey.h"
   1.126 +
   1.127  TestCase(ParseCert) {
   1.128      NSData *cert = [NSData dataWithContentsOfFile: @"../../Tests/selfsigned.cer"];
   1.129      NSError *error = nil;
   1.130 @@ -288,6 +324,14 @@
   1.131      CAssertNil(error);
   1.132      NSString *dump = [MYASN1Object dump: parsed];
   1.133      CAssert(dump);
   1.134 +    Log(@"Parsed selfsigned.cer:\n%@", dump);
   1.135 +    
   1.136 +    MYCertificate *myCert = [[MYCertificate alloc] initWithCertificateData: cert];
   1.137 +    CAssert(myCert);
   1.138 +    const CSSM_KEY *pubKey = myCert.publicKey.cssmKey;
   1.139 +    CSSM_DATA pubKeyData = pubKey->KeyData;
   1.140 +    id parsedPubKey = MYBERParse([NSData dataWithBytes: pubKeyData.Data length: pubKeyData.Length],NULL);
   1.141 +    Log(@"Parsed public key:\n%@", [MYASN1Object dump: parsedPubKey]);
   1.142  
   1.143      cert = [NSData dataWithContentsOfFile: @"../../Tests/iphonedev.cer"];
   1.144      parsed = MYBERParse(cert,&error);