/* * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). * You may not use this file except in compliance with the License. Please obtain * a copy of the License at http://www.apple.com/publicsource and read it before * using this file. * * This Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the * specific language governing rights and limitations under the License. */ // // Tester - test driver for securityserver client side. // #include "testclient.h" #include "testutils.h" // // Simple run-through. // This generates an RSA key, tests cleartext retrieval, signs a message, // and veries it both ways. // This is a basic integrity regression for the SecurityServer. // void signWithRSA() { printf("* RSA key signing test\n"); CSP csp(gGuidAppleCSP); ClientSession ss(CssmAllocator::standard(), CssmAllocator::standard()); StringData data("To sign or not to sign, is that the question?"); // set up dummy credentials CssmKey dummyKey; memset(&dummyKey, 0, sizeof(dummyKey)); CssmData nullData; // generate a key detail("Asking for RSA key generation"); KeyHandle publicKey, privateKey; const CssmCryptoData seed(StringData("Seed ye well, my friend, and ye shall reap...")); FakeContext genContext(CSSM_ALGCLASS_KEYGEN, CSSM_ALGID_RSA, &::Context::Attr(CSSM_ATTRIBUTE_KEY_LENGTH, 512), &::Context::Attr(CSSM_ATTRIBUTE_SEED, seed), NULL); CssmKey::Header pubHeader, privHeader; ss.generateKey(noDb, genContext, CSSM_KEYUSE_VERIFY, CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_RETURN_DATA, CSSM_KEYUSE_SIGN, CSSM_KEYATTR_SENSITIVE, NULL/*cred*/, NULL/*owner*/, publicKey, pubHeader, privateKey, privHeader); detail("Key pair generated"); // retrieve the public key CssmKey cpk; FakeContext wrapContext(CSSM_ALGCLASS_SYMMETRIC, CSSM_ALGID_NONE, 0); ss.wrapKey(wrapContext, noKey, publicKey, &nullCred, NULL, cpk); Key clearPublicKey(csp, cpk); detail("Retrieved public key"); // make sure we can't retrieve the private key CssmKey clearPrivateKey; try { ss.wrapKey(wrapContext, noKey, privateKey, NULL/*cred*/, NULL, clearPrivateKey); error("SecurityServer ACTUALLY gave us the PRIVATE key bits!"); } catch (CssmError &err) { detail(err, "Private key retrieval properly rejected"); } // sign a message CssmData signature; FakeContext signContext(CSSM_ALGCLASS_SIGNATURE, CSSM_ALGID_SHA1WithRSA, &::Context::Attr(CSSM_ATTRIBUTE_KEY, dummyKey), NULL); ss.generateSignature(signContext, privateKey, data, signature); detail("Signature generated by SecurityServer"); // verify the signature (local) { Verify verifier(csp, CSSM_ALGID_SHA1WithRSA); verifier.key(clearPublicKey); verifier.verify(data, signature); detail("Signature verified locally"); } // verify the signature (SS) ss.verifySignature(signContext, publicKey, data, signature); detail("Signature verified by SecurityServer"); // falsify the signature (SS) DataBuffer<200> falseData; memcpy(falseData.data(), data.data(), data.length()); falseData.length(data.length()); ((char *)falseData)[3] = '?'; // alter message try { ss.verifySignature(signContext, publicKey, falseData, signature); error("Altered message incorrectly verifies"); } catch (CssmError &err) { if (err.cssmError() == CSSMERR_CSP_VERIFY_FAILED) detail("Verify of altered message successfully failed"); else error(err, "Unexpected exception on verify failure test"); } } // // Encrypt with DES // void desEncryption() { printf("* DES encryption test\n"); ClientSession ss(CssmAllocator::standard(), CssmAllocator::standard()); CSP csp(gGuidAppleCSP); StringData clearText("Insert witty quotation here."); StringData iv("abcdefgh"); // make up a DES key StringData keyBits(strdup("Wallaby!")); CssmKey keyForm(keyBits); keyForm.header().KeyClass = CSSM_KEYCLASS_SESSION_KEY; keyForm.header().BlobType = CSSM_KEYBLOB_RAW; keyForm.header().AlgorithmId = CSSM_ALGID_DES; keyForm.header().Format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING; Key key(csp, keyForm); // encrypt locally DataBuffer<200> localCipher; Encrypt localCrypt(csp, CSSM_ALGID_DES); localCrypt.mode(CSSM_ALGMODE_CBC_IV8); localCrypt.padding(CSSM_PADDING_PKCS1); localCrypt.initVector(iv); localCrypt.key(key); CssmData remData; size_t localLen = localCrypt.encrypt(clearText, localCipher, remData); if (remData) error("LOCAL ENCRYPTION OVERFLOWED"); localCipher.length(localLen); detail("Locally encrypted %ld bytes", localLen); // wrap in the key CssmData unwrappedData; ResourceControlContext owner; FakeContext unwrapContext(CSSM_ALGCLASS_SYMMETRIC, CSSM_ALGID_NONE, 0); KeyHandle keyRef; CssmKey::Header keyHeader; ss.unwrapKey(noDb, unwrapContext, noKey, noKey, key, CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, CSSM_KEYATTR_RETURN_DEFAULT, NULL/*cred*/, NULL/*owner*/, unwrappedData, keyRef, keyHeader); detail("Placed key into SecurityServer; handle=%lx", keyRef); // encrypt remotely and compare const CssmKey &tKey = key; FakeContext cryptoContext(CSSM_ALGCLASS_SYMMETRIC, CSSM_ALGID_DES, &::Context::Attr(CSSM_ATTRIBUTE_KEY, keyForm), &::Context::Attr(CSSM_ATTRIBUTE_INIT_VECTOR, iv), &::Context::Attr(CSSM_ATTRIBUTE_MODE, CSSM_ALGMODE_CBC_IV8), &::Context::Attr(CSSM_ATTRIBUTE_PADDING, CSSM_PADDING_PKCS1), NULL); CssmData remoteCipher; ss.encrypt(cryptoContext, keyRef, clearText, remoteCipher); detail("Plaintext encrypted on SecurityServer"); if (remoteCipher == localCipher) detail("Ciphertexts verified"); else error("CIPHERTEXTS DIFFER"); // decrypt in SecurityServer DataBuffer<200> clearRecovered; ss.decrypt(cryptoContext, keyRef, localCipher, clearRecovered); detail("Decrypted ciphertext in SecurityServer"); if (clearRecovered == clearText) detail("Plaintext recovered"); else error("PLAINTEXT MISMATCH"); }