1/*
2 * Copyright (c) 2000-2001,2004 Apple Computer, Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25//
26// Tester - test driver for securityserver client side.
27//
28#include "testclient.h"
29#include "testutils.h"
30
31
32//
33// Simple run-through.
34// This generates an RSA key, tests cleartext retrieval, signs a message,
35// and veries it both ways.
36// This is a basic integrity regression for the SecurityServer.
37//
38void signWithRSA()
39{
40	printf("* RSA key signing test\n");
41	CSP csp(gGuidAppleCSP);
42	ClientSession ss(CssmAllocator::standard(), CssmAllocator::standard());
43	StringData data("To sign or not to sign, is that the question?");
44
45	// set up dummy credentials
46	CssmKey dummyKey; memset(&dummyKey, 0, sizeof(dummyKey));
47	CssmData nullData;
48
49	// generate a key
50	detail("Asking for RSA key generation");
51	KeyHandle publicKey, privateKey;
52	const CssmCryptoData seed(StringData("Seed ye well, my friend, and ye shall reap..."));
53	FakeContext genContext(CSSM_ALGCLASS_KEYGEN, CSSM_ALGID_RSA,
54		&::Context::Attr(CSSM_ATTRIBUTE_KEY_LENGTH, 512),
55		&::Context::Attr(CSSM_ATTRIBUTE_SEED, seed),
56		NULL);
57    CssmKey::Header pubHeader, privHeader;
58	ss.generateKey(noDb, genContext,
59		CSSM_KEYUSE_VERIFY, CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_RETURN_DATA,
60		CSSM_KEYUSE_SIGN, CSSM_KEYATTR_SENSITIVE,
61		NULL/*cred*/, NULL/*owner*/, publicKey, pubHeader, privateKey, privHeader);
62	detail("Key pair generated");
63
64	// retrieve the public key
65	CssmKey cpk;
66	FakeContext wrapContext(CSSM_ALGCLASS_SYMMETRIC, CSSM_ALGID_NONE, 0);
67	ss.wrapKey(wrapContext, noKey, publicKey, &nullCred, NULL, cpk);
68    Key clearPublicKey(csp, cpk);
69	detail("Retrieved public key");
70
71	// make sure we can't retrieve the private key
72	CssmKey clearPrivateKey;
73	try {
74		ss.wrapKey(wrapContext, noKey, privateKey, NULL/*cred*/, NULL, clearPrivateKey);
75		error("SecurityServer ACTUALLY gave us the PRIVATE key bits!");
76	} catch (CssmError &err) {
77		detail(err, "Private key retrieval properly rejected");
78	}
79
80	// sign a message
81	CssmData signature;
82	FakeContext signContext(CSSM_ALGCLASS_SIGNATURE, CSSM_ALGID_SHA1WithRSA,
83		&::Context::Attr(CSSM_ATTRIBUTE_KEY, dummyKey),
84		NULL);
85	ss.generateSignature(signContext, privateKey, data, signature);
86	detail("Signature generated by SecurityServer");
87
88	// verify the signature (local)
89	{
90		Verify verifier(csp, CSSM_ALGID_SHA1WithRSA);
91		verifier.key(clearPublicKey);
92		verifier.verify(data, signature);
93		detail("Signature verified locally");
94	}
95
96	// verify the signature (SS)
97	ss.verifySignature(signContext, publicKey, data, signature);
98	detail("Signature verified by SecurityServer");
99
100	// falsify the signature (SS)
101	DataBuffer<200> falseData;
102	memcpy(falseData.data(), data.data(), data.length());
103	falseData.length(data.length());
104	((char *)falseData)[3] = '?';	// alter message
105	try {
106		ss.verifySignature(signContext, publicKey, falseData, signature);
107		error("Altered message incorrectly verifies");
108	} catch (CssmError &err) {
109		if (err.cssmError() == CSSMERR_CSP_VERIFY_FAILED)
110			detail("Verify of altered message successfully failed");
111		else
112			error(err, "Unexpected exception on verify failure test");
113	}
114}
115
116
117//
118// Encrypt with DES
119//
120void desEncryption()
121{
122	printf("* DES encryption test\n");
123	ClientSession ss(CssmAllocator::standard(), CssmAllocator::standard());
124	CSP csp(gGuidAppleCSP);
125
126	StringData clearText("Insert witty quotation here.");
127	StringData iv("abcdefgh");
128
129	// make up a DES key
130	StringData keyBits(strdup("Wallaby!"));
131	CssmKey keyForm(keyBits);
132	keyForm.header().KeyClass = CSSM_KEYCLASS_SESSION_KEY;
133	keyForm.header().BlobType = CSSM_KEYBLOB_RAW;
134	keyForm.header().AlgorithmId = CSSM_ALGID_DES;
135	keyForm.header().Format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING;
136    Key key(csp, keyForm);
137
138	// encrypt locally
139	DataBuffer<200> localCipher;
140	Encrypt localCrypt(csp, CSSM_ALGID_DES);
141	localCrypt.mode(CSSM_ALGMODE_CBC_IV8);
142	localCrypt.padding(CSSM_PADDING_PKCS1);
143	localCrypt.initVector(iv);
144	localCrypt.key(key);
145	CssmData remData;
146	size_t localLen = localCrypt.encrypt(clearText, localCipher, remData);
147	if (remData)
148		error("LOCAL ENCRYPTION OVERFLOWED");
149	localCipher.length(localLen);
150	detail("Locally encrypted %ld bytes", localLen);
151
152	// wrap in the key
153	CssmData unwrappedData;
154	ResourceControlContext owner;
155	FakeContext unwrapContext(CSSM_ALGCLASS_SYMMETRIC, CSSM_ALGID_NONE, 0);
156	KeyHandle keyRef;
157    CssmKey::Header keyHeader;
158    ss.unwrapKey(noDb, unwrapContext, noKey, noKey,
159		key,
160		CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT,
161		CSSM_KEYATTR_RETURN_DEFAULT,
162		NULL/*cred*/, NULL/*owner*/, unwrappedData, keyRef, keyHeader);
163	detail("Placed key into SecurityServer; handle=%lx", keyRef);
164
165	// encrypt remotely and compare
166	const CssmKey &tKey = key;
167	FakeContext cryptoContext(CSSM_ALGCLASS_SYMMETRIC, CSSM_ALGID_DES,
168		&::Context::Attr(CSSM_ATTRIBUTE_KEY, keyForm),
169		&::Context::Attr(CSSM_ATTRIBUTE_INIT_VECTOR, iv),
170		&::Context::Attr(CSSM_ATTRIBUTE_MODE, CSSM_ALGMODE_CBC_IV8),
171		&::Context::Attr(CSSM_ATTRIBUTE_PADDING, CSSM_PADDING_PKCS1),
172		NULL);
173	CssmData remoteCipher;
174	ss.encrypt(cryptoContext, keyRef, clearText, remoteCipher);
175	detail("Plaintext encrypted on SecurityServer");
176	if (remoteCipher == localCipher)
177		detail("Ciphertexts verified");
178	else
179		error("CIPHERTEXTS DIFFER");
180
181	// decrypt in SecurityServer
182	DataBuffer<200> clearRecovered;
183	ss.decrypt(cryptoContext, keyRef, localCipher, clearRecovered);
184	detail("Decrypted ciphertext in SecurityServer");
185	if (clearRecovered == clearText)
186		detail("Plaintext recovered");
187	else
188		error("PLAINTEXT MISMATCH");
189}
190
191