MYCertificateTest.m
author Jens Alfke <jens@mooseyard.com>
Tue Jul 21 10:13:08 2009 -0700 (2009-07-21)
changeset 27 d0aadddb9c64
permissions -rw-r--r--
MYCertificate now checks validity of self-signed certs loaded from the keychain (because the Security framework doesn't validate self-signed certs.)
     1 //
     2 //  MYCertificateTest.m
     3 //  MYCrypto-iPhone
     4 //
     5 //  Created by Jens Alfke on 6/15/09.
     6 //  Copyright 2009 Jens Alfke. All rights reserved.
     7 //
     8 
     9 #import "MYCertificateInfo.h"
    10 #import "MYCrypto.h"
    11 #import "MYCrypto_Private.h"
    12 
    13 
    14 #if DEBUG
    15 
    16 
    17 static MYCertificateInfo* testCertData(NSData *certData, BOOL selfSigned) {
    18     //Log(@"Cert Data =\n%@", certData);
    19     CAssert(certData!=nil);
    20     NSError *error = nil;
    21     MYCertificateInfo *pcert = [[MYCertificateInfo alloc] initWithCertificateData: certData 
    22                                                                             error: &error];
    23     CAssertNil(error);
    24     CAssert(pcert != nil);
    25     
    26     CAssertEq(pcert.isRoot, selfSigned);
    27         
    28     MYCertificateName *subject = pcert.subject;
    29     Log(@"Common Name = %@", subject.commonName);
    30     Log(@"Given Name  = %@", subject.givenName);
    31     Log(@"Surname     = %@", subject.surname);
    32     Log(@"Desc        = %@", subject.nameDescription);
    33     Log(@"Email       = %@", subject.emailAddress);
    34     CAssert(subject.commonName);
    35     
    36     MYPublicKey *pcertKey = pcert.subjectPublicKey;
    37     Log(@"Subject Public Key = %@", pcertKey);
    38     CAssert(pcertKey);
    39     
    40     // Now go through MYCertificate:
    41     Log(@"Creating a MYCertificate from the data...");
    42     MYCertificate *cert = [[MYCertificate alloc] initWithCertificateData: certData];
    43     Log(@"MYCertificate = %@", cert);
    44     CAssert(cert);
    45     CAssertEqual(cert.info, pcert);
    46     Log(@"Trust = %@", MYTrustResultDescribe([cert evaluateTrust]));
    47     
    48     MYPublicKey *certKey = cert.publicKey;
    49     Log(@"MYCertificate public key = ", certKey);
    50     CAssertEqual(certKey.keyData, pcert.subjectPublicKey.keyData);
    51     [cert release];
    52     /*TEMP
    53     Log(@"Adding to keychain...");
    54     cert = [[MYKeychain defaultKeychain] importCertificate: certData];
    55     Log(@"Imported as %@", cert);
    56     //CAssert(cert);
    57     if (cert) {
    58         Log(@"Removing from keychain...");
    59         CAssert([cert removeFromKeychain]);
    60     }
    61     */
    62     return pcert;
    63 }
    64 
    65 static NSData* readTestFile(NSString *filename) {
    66 #if TARGET_OS_IPHONE
    67     filename = [[NSBundle mainBundle] pathForResource: filename ofType: @"cer"];
    68 #else
    69     filename = [[@"../../Tests/" stringByAppendingPathComponent: filename]
    70                 stringByAppendingPathExtension: @"cer"];
    71 #endif
    72     Log(@"--- Testing certificate file %@", filename);
    73     NSData *data = [NSData dataWithContentsOfFile: filename];
    74     CAssert(data, @"Couldn't read file %@", filename);
    75     return data;
    76 }
    77 
    78 static MYCertificateInfo* testCert(NSString *filename, BOOL selfSigned) {
    79     return testCertData(readTestFile(filename), selfSigned);
    80 }
    81 
    82 
    83 TestCase(ParsedCert) {
    84     testCert(@"selfsigned", YES);
    85     testCert(@"iphonedev", NO);
    86     
    87     // Now test a self-signed cert with a bad signature:
    88     MYCertificate *cert = [[MYCertificate alloc] initWithCertificateData: readTestFile(@"selfsigned_altered")];
    89     Log(@"MYCertificate = %@", cert);
    90     CAssertNil(cert);
    91 }
    92 
    93 
    94 #import "MYCrypto_Private.h"
    95 
    96 TestCase(CreateCert) {
    97     MYPrivateKey *privateKey = [[MYKeychain defaultKeychain] generateRSAKeyPairOfSize: 512];
    98     CAssert(privateKey);
    99     Log(@"---- Generated key-pair with %@, %@", privateKey.publicKey, privateKey);
   100     MYIdentity *identity = nil;
   101     @try{
   102         MYCertificateRequest *pcert = [[MYCertificateRequest alloc] initWithPublicKey: privateKey.publicKey];
   103         MYCertificateName *subject = pcert.subject;
   104         subject.commonName = @"testcase";
   105         subject.givenName = @"Test";
   106         subject.surname = @"Case";
   107         subject.nameDescription = @"Just a test certificate created by MYCrypto";
   108         subject.emailAddress = @"testcase@example.com";
   109 
   110         subject = pcert.subject;
   111         CAssertEqual(subject.commonName, @"testcase");
   112         CAssertEqual(subject.givenName, @"Test");
   113         CAssertEqual(subject.surname, @"Case");
   114         CAssertEqual(subject.nameDescription, @"Just a test certificate created by MYCrypto");
   115         CAssertEqual(subject.emailAddress, @"testcase@example.com");
   116         
   117         CAssertEqual(pcert.subjectPublicKey.keyData, privateKey.publicKey.keyData);
   118         
   119         Log(@"---- Signing...");
   120         NSError *error;
   121         NSData *certData = [pcert selfSignWithPrivateKey: privateKey error: &error];
   122         Log(@"Generated cert = \n%@", certData);
   123         CAssert(certData);
   124         CAssertNil(error);
   125         CAssert(certData);
   126         MYCertificateInfo *pcert2 = testCertData(certData, YES);
   127         
   128         Log(@"---- Verifying Info...");
   129         MYCertificateName *subject2 = pcert2.subject;
   130         CAssertEqual(subject2,subject);
   131         CAssertEqual(subject2.commonName, @"testcase");
   132         CAssertEqual(subject2.givenName, @"Test");
   133         CAssertEqual(subject2.surname, @"Case");
   134         CAssertEqual(subject2.nameDescription, @"Just a test certificate created by MYCrypto");
   135         CAssertEqual(subject2.emailAddress, @"testcase@example.com");
   136                 
   137         Log(@"---- Creating MYCertificate object...");
   138         MYCertificate *cert = [[MYCertificate alloc] initWithCertificateData: certData];
   139         Log(@"Loaded %@", cert);
   140         CAssert(cert);
   141         MYPublicKey *certKey = cert.publicKey;
   142         Log(@"Its public key has name %@", certKey.name);//TEMP
   143         Log(@"Its public key = %@", certKey);
   144         CAssertEqual(certKey.keyData, privateKey.publicKey.keyData);
   145         Log(@"X.509 trust = %@", MYTrustResultDescribe([cert evaluateTrust]));
   146         Log(@"SSL trust = %@", MYTrustResultDescribe([cert evaluateTrustWithPolicy: [MYCertificate SSLPolicy]]));
   147         
   148         Log(@"---- Adding cert to keychain...");
   149         MYCertificate *addedCert = [[MYKeychain defaultKeychain] importCertificate: certData];
   150         Log(@"Imported as %@", addedCert);
   151         //CAssert(addedCert);
   152         if (addedCert)
   153             CAssert([addedCert removeFromKeychain]);
   154         
   155         Log(@"---- Creating Identity...");
   156         identity = [pcert createSelfSignedIdentityWithPrivateKey: privateKey error: &error];
   157         Log(@"Identity = %@", identity);
   158         CAssert(identity);
   159         CAssertNil(error);
   160         CAssertEqual(identity.keychain, [MYKeychain defaultKeychain]);
   161         CAssertEqual(identity.privateKey.publicKeyDigest, privateKey.publicKeyDigest);
   162         CAssert([identity isEqualToCertificate: cert]);
   163         
   164         [pcert release];
   165         
   166     } @finally {
   167         // [privateKey removeFromKeychain];
   168         // [identity removeFromKeychain];
   169         // Currently I'm leaving them in, so the EnumerateXXX tests can chew on them later.
   170     }
   171 }
   172 
   173 #endif
   174 
   175 
   176 /*
   177  Copyright (c) 2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
   178  
   179  Redistribution and use in source and binary forms, with or without modification, are permitted
   180  provided that the following conditions are met:
   181  
   182  * Redistributions of source code must retain the above copyright notice, this list of conditions
   183  and the following disclaimer.
   184  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
   185  and the following disclaimer in the documentation and/or other materials provided with the
   186  distribution.
   187  
   188  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
   189  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
   190  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
   191  BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   192  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
   193   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   194  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
   195  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   196  */