X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/securityd/tests/testcrypto.cpp?ds=sidebyside diff --git a/securityd/tests/testcrypto.cpp b/securityd/tests/testcrypto.cpp new file mode 100644 index 00000000..f6201106 --- /dev/null +++ b/securityd/tests/testcrypto.cpp @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +// +// 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"); +} +