]> git.saurik.com Git - apple/security.git/blobdiff - securityd/tests/testcrypto.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / securityd / tests / testcrypto.cpp
diff --git a/securityd/tests/testcrypto.cpp b/securityd/tests/testcrypto.cpp
new file mode 100644 (file)
index 0000000..f620110
--- /dev/null
@@ -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");
+}
+