jens@26: // jens@26: // MYCertificateTest.m jens@26: // MYCrypto-iPhone jens@26: // jens@26: // Created by Jens Alfke on 6/15/09. jens@26: // Copyright 2009 Jens Alfke. All rights reserved. jens@26: // jens@26: jens@26: #import "MYCertificateInfo.h" jens@26: #import "MYCrypto.h" jens@26: #import "MYCrypto_Private.h" jens@26: jens@26: jens@26: #if DEBUG jens@26: jens@26: jens@26: static MYCertificateInfo* testCertData(NSData *certData, BOOL selfSigned) { jens@26: //Log(@"Cert Data =\n%@", certData); jens@26: CAssert(certData!=nil); jens@26: NSError *error = nil; jens@26: MYCertificateInfo *pcert = [[MYCertificateInfo alloc] initWithCertificateData: certData jens@26: error: &error]; jens@26: CAssertNil(error); jens@26: CAssert(pcert != nil); jens@26: jens@26: CAssertEq(pcert.isRoot, selfSigned); jens@26: jens@26: MYCertificateName *subject = pcert.subject; jens@26: Log(@"Common Name = %@", subject.commonName); jens@26: Log(@"Given Name = %@", subject.givenName); jens@26: Log(@"Surname = %@", subject.surname); jens@26: Log(@"Desc = %@", subject.nameDescription); jens@26: Log(@"Email = %@", subject.emailAddress); jens@26: CAssert(subject.commonName); jens@26: jens@26: MYPublicKey *pcertKey = pcert.subjectPublicKey; jens@26: Log(@"Subject Public Key = %@", pcertKey); jens@26: CAssert(pcertKey); jens@26: jens@26: // Now go through MYCertificate: jens@26: Log(@"Creating a MYCertificate from the data..."); jens@26: MYCertificate *cert = [[MYCertificate alloc] initWithCertificateData: certData]; jens@26: Log(@"MYCertificate = %@", cert); jens@26: CAssert(cert); jens@26: CAssertEqual(cert.info, pcert); jens@26: Log(@"Trust = %@", MYTrustResultDescribe([cert evaluateTrust])); jens@26: jens@26: MYPublicKey *certKey = cert.publicKey; jens@26: Log(@"MYCertificate public key = ", certKey); jens@26: CAssertEqual(certKey.keyData, pcert.subjectPublicKey.keyData); jens@26: [cert release]; jens@26: /*TEMP jens@26: Log(@"Adding to keychain..."); jens@26: cert = [[MYKeychain defaultKeychain] importCertificate: certData]; jens@26: Log(@"Imported as %@", cert); jens@26: //CAssert(cert); jens@26: if (cert) { jens@26: Log(@"Removing from keychain..."); jens@26: CAssert([cert removeFromKeychain]); jens@26: } jens@26: */ jens@26: return pcert; jens@26: } jens@26: jens@26: static NSData* readTestFile(NSString *filename) { jens@26: #if TARGET_OS_IPHONE jens@26: filename = [[NSBundle mainBundle] pathForResource: filename ofType: @"cer"]; jens@26: #else jens@26: filename = [[@"../../Tests/" stringByAppendingPathComponent: filename] jens@26: stringByAppendingPathExtension: @"cer"]; jens@26: #endif jens@26: Log(@"--- Testing certificate file %@", filename); jens@26: NSData *data = [NSData dataWithContentsOfFile: filename]; jens@26: CAssert(data, @"Couldn't read file %@", filename); jens@26: return data; jens@26: } jens@26: jens@26: static MYCertificateInfo* testCert(NSString *filename, BOOL selfSigned) { jens@26: return testCertData(readTestFile(filename), selfSigned); jens@26: } jens@26: jens@26: jens@26: TestCase(ParsedCert) { jens@26: testCert(@"selfsigned", YES); jens@26: testCert(@"iphonedev", NO); jens@26: jens@26: // Now test a self-signed cert with a bad signature: jens@26: MYCertificate *cert = [[MYCertificate alloc] initWithCertificateData: readTestFile(@"selfsigned_altered")]; jens@26: Log(@"MYCertificate = %@", cert); jens@26: CAssertNil(cert); jens@26: } jens@26: jens@26: jens@26: #import "MYCrypto_Private.h" jens@26: jens@26: TestCase(CreateCert) { jens@26: MYPrivateKey *privateKey = [[MYKeychain defaultKeychain] generateRSAKeyPairOfSize: 512]; jens@26: CAssert(privateKey); jens@26: Log(@"---- Generated key-pair with %@, %@", privateKey.publicKey, privateKey); jens@26: MYIdentity *identity = nil; jens@26: @try{ jens@26: MYCertificateRequest *pcert = [[MYCertificateRequest alloc] initWithPublicKey: privateKey.publicKey]; jens@26: MYCertificateName *subject = pcert.subject; jens@26: subject.commonName = @"testcase"; jens@26: subject.givenName = @"Test"; jens@26: subject.surname = @"Case"; jens@26: subject.nameDescription = @"Just a test certificate created by MYCrypto"; jens@26: subject.emailAddress = @"testcase@example.com"; jens@26: jens@26: subject = pcert.subject; jens@26: CAssertEqual(subject.commonName, @"testcase"); jens@26: CAssertEqual(subject.givenName, @"Test"); jens@26: CAssertEqual(subject.surname, @"Case"); jens@26: CAssertEqual(subject.nameDescription, @"Just a test certificate created by MYCrypto"); jens@26: CAssertEqual(subject.emailAddress, @"testcase@example.com"); jens@26: jens@26: CAssertEqual(pcert.subjectPublicKey.keyData, privateKey.publicKey.keyData); jens@26: jens@26: Log(@"---- Signing..."); jens@26: NSError *error; jens@26: NSData *certData = [pcert selfSignWithPrivateKey: privateKey error: &error]; jens@26: Log(@"Generated cert = \n%@", certData); jens@26: CAssert(certData); jens@26: CAssertNil(error); jens@26: CAssert(certData); jens@26: MYCertificateInfo *pcert2 = testCertData(certData, YES); jens@26: jens@26: Log(@"---- Verifying Info..."); jens@26: MYCertificateName *subject2 = pcert2.subject; jens@26: CAssertEqual(subject2,subject); jens@26: CAssertEqual(subject2.commonName, @"testcase"); jens@26: CAssertEqual(subject2.givenName, @"Test"); jens@26: CAssertEqual(subject2.surname, @"Case"); jens@26: CAssertEqual(subject2.nameDescription, @"Just a test certificate created by MYCrypto"); jens@26: CAssertEqual(subject2.emailAddress, @"testcase@example.com"); jens@26: jens@26: Log(@"---- Creating MYCertificate object..."); jens@26: MYCertificate *cert = [[MYCertificate alloc] initWithCertificateData: certData]; jens@26: Log(@"Loaded %@", cert); jens@26: CAssert(cert); jens@26: MYPublicKey *certKey = cert.publicKey; jens@26: Log(@"Its public key has name %@", certKey.name);//TEMP jens@26: Log(@"Its public key = %@", certKey); jens@26: CAssertEqual(certKey.keyData, privateKey.publicKey.keyData); jens@26: Log(@"X.509 trust = %@", MYTrustResultDescribe([cert evaluateTrust])); jens@26: Log(@"SSL trust = %@", MYTrustResultDescribe([cert evaluateTrustWithPolicy: [MYCertificate SSLPolicy]])); jens@26: jens@26: Log(@"---- Adding cert to keychain..."); jens@26: MYCertificate *addedCert = [[MYKeychain defaultKeychain] importCertificate: certData]; jens@26: Log(@"Imported as %@", addedCert); jens@26: //CAssert(addedCert); jens@26: if (addedCert) jens@26: CAssert([addedCert removeFromKeychain]); jens@26: jens@26: Log(@"---- Creating Identity..."); jens@26: identity = [pcert createSelfSignedIdentityWithPrivateKey: privateKey error: &error]; jens@26: Log(@"Identity = %@", identity); jens@26: CAssert(identity); jens@26: CAssertNil(error); jens@26: CAssertEqual(identity.keychain, [MYKeychain defaultKeychain]); jens@26: CAssertEqual(identity.privateKey.publicKeyDigest, privateKey.publicKeyDigest); jens@26: CAssert([identity isEqualToCertificate: cert]); jens@26: jens@26: [pcert release]; jens@26: jens@26: } @finally { jens@26: // [privateKey removeFromKeychain]; jens@26: // [identity removeFromKeychain]; jens@26: // Currently I'm leaving them in, so the EnumerateXXX tests can chew on them later. jens@26: } jens@26: } jens@26: jens@26: #endif jens@26: jens@26: jens@26: /* jens@26: Copyright (c) 2009, Jens Alfke . All rights reserved. jens@26: jens@26: Redistribution and use in source and binary forms, with or without modification, are permitted jens@26: provided that the following conditions are met: jens@26: jens@26: * Redistributions of source code must retain the above copyright notice, this list of conditions jens@26: and the following disclaimer. jens@26: * Redistributions in binary form must reproduce the above copyright notice, this list of conditions jens@26: and the following disclaimer in the documentation and/or other materials provided with the jens@26: distribution. jens@26: jens@26: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR jens@26: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND jens@26: FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI- jens@26: BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES jens@26: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR jens@26: PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN jens@26: CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF jens@26: THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. jens@26: */