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// testutils - utilities for unit test drivers 27// 28#include "testutils.h" 29 30using namespace CssmClient; 31 32bool verbose = false; 33 34 35// 36// Error and diagnostic drivers 37// 38void error(const char *msg = NULL, ...) 39{ 40 if (msg) { 41 va_list args; 42 va_start(args, msg); 43 vfprintf(stderr, msg, args); 44 va_end(args); 45 putc('\n', stderr); 46 } 47 abort(); 48} 49 50void error(const CssmCommonError &err, const char *msg = NULL, ...) 51{ 52 if (msg) { 53 va_list args; 54 va_start(args, msg); 55 vfprintf(stderr, msg, args); 56 va_end(args); 57 fprintf(stderr, ": %s", cssmErrorString(err.cssmError()).c_str()); 58 putc('\n', stderr); 59 } 60 abort(); 61} 62 63void detail(const char *msg = NULL, ...) 64{ 65 if (verbose) { 66 va_list args; 67 va_start(args, msg); 68 vfprintf(stdout, msg, args); 69 va_end(args); 70 putc('\n', stdout); 71 } 72} 73 74void detail(const CssmCommonError &err, const char *msg) 75{ 76 if (verbose) 77 printf("%s (ok): %s\n", msg, cssmErrorString(err).c_str()); 78} 79 80void prompt(const char *msg) 81{ 82 if (isatty(fileno(stdin))) 83 printf("[%s]", msg); 84} 85 86void prompt() 87{ 88 if (isatty(fileno(stdin))) 89 printf(" OK\n"); 90} 91 92 93// 94// FakeContext management 95// 96FakeContext::FakeContext(CSSM_CONTEXT_TYPE type, CSSM_ALGORITHMS alg, uint32 count) 97: Context(type, alg) 98{ 99 NumberOfAttributes = count; 100 ContextAttributes = new Attr[count]; 101} 102 103 104FakeContext::FakeContext(CSSM_CONTEXT_TYPE type, CSSM_ALGORITHMS alg, ...) 105: Context(type, alg) 106{ 107 // count arguments 108 va_list args; 109 va_start(args, alg); 110 uint32 count = 0; 111 while (va_arg(args, Attr *)) 112 count++; 113 va_end(args); 114 115 // make vector 116 NumberOfAttributes = count; 117 ContextAttributes = new Attr[count]; 118 119 // stuff vector 120 va_start(args, alg); 121 for (uint32 n = 0; n < count; n++) 122 (*this)[n] = *va_arg(args, Attr *); 123 va_end(args); 124} 125 126 127// 128// ACL test driver class 129// 130AclTester::AclTester(ClientSession &ss, const AclEntryInput *acl) : session(ss) 131{ 132 // make up a DES key 133 StringData keyBits("Tweedle!"); 134 CssmKey key(keyBits); 135 key.header().KeyClass = CSSM_KEYCLASS_SESSION_KEY; 136 137 // wrap in the key 138 CssmData unwrappedData; 139 FakeContext unwrapContext(CSSM_ALGCLASS_SYMMETRIC, CSSM_ALGID_NONE, 0); 140 CssmKey::Header keyHeader; 141 ss.unwrapKey(noDb, unwrapContext, noKey, noKey, 142 key, 143 CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, 144 CSSM_KEYATTR_EXTRACTABLE, 145 NULL /*cred*/, acl, 146 unwrappedData, keyRef, keyHeader); 147 detail("Key seeded with ACL"); 148} 149 150 151void AclTester::testWrap(const AccessCredentials *cred, const char *howWrong) 152{ 153 FakeContext wrapContext(CSSM_ALGCLASS_SYMMETRIC, CSSM_ALGID_NONE, 0); 154 CssmWrappedKey wrappedKey; 155 try { 156 session.wrapKey(wrapContext, noKey, keyRef, 157 cred, NULL /*descriptive*/, wrappedKey); 158 if (howWrong) { 159 error("WRAP MISTAKENLY SUCCEEDED: %s", howWrong); 160 } 161 detail("extract OK"); 162 } catch (const CssmCommonError &err) { 163 if (!howWrong) 164 error(err, "FAILED TO EXTRACT KEY"); 165 detail(err, "extract failed OK"); 166 } 167} 168 169void AclTester::testEncrypt(const AccessCredentials *cred, const char *howWrong) 170{ 171 CssmKey keyForm; memset(&keyForm, 0, sizeof(keyForm)); 172 StringData iv("Aardvark"); 173 StringData clearText("blah"); 174 CssmData remoteCipher; 175 try { 176 if (cred) { 177 FakeContext cryptoContext(CSSM_ALGCLASS_SYMMETRIC, CSSM_ALGID_DES, 178 &::Context::Attr(CSSM_ATTRIBUTE_KEY, keyForm), 179 &::Context::Attr(CSSM_ATTRIBUTE_INIT_VECTOR, iv), 180 &::Context::Attr(CSSM_ATTRIBUTE_MODE, CSSM_ALGMODE_CBC_IV8), 181 &::Context::Attr(CSSM_ATTRIBUTE_PADDING, CSSM_PADDING_PKCS1), 182 &::Context::Attr(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, *cred), 183 NULL); 184 session.encrypt(cryptoContext, keyRef, clearText, remoteCipher); 185 } else { 186 FakeContext cryptoContext(CSSM_ALGCLASS_SYMMETRIC, CSSM_ALGID_DES, 187 &::Context::Attr(CSSM_ATTRIBUTE_KEY, keyForm), 188 &::Context::Attr(CSSM_ATTRIBUTE_INIT_VECTOR, iv), 189 &::Context::Attr(CSSM_ATTRIBUTE_MODE, CSSM_ALGMODE_CBC_IV8), 190 &::Context::Attr(CSSM_ATTRIBUTE_PADDING, CSSM_PADDING_PKCS1), 191 NULL); 192 session.encrypt(cryptoContext, keyRef, clearText, remoteCipher); 193 } 194 if (howWrong) { 195 error("ENCRYPT MISTAKENLY SUCCEEDED: %s", howWrong); 196 } 197 detail("encrypt OK"); 198 } catch (CssmCommonError &err) { 199 if (!howWrong) 200 error(err, "FAILED TO ENCRYPT"); 201 detail(err, "encrypt failed"); 202 } 203} 204 205 206// 207// Database test driver class 208// 209DbTester::DbTester(ClientSession &ss, const char *path, 210 const AccessCredentials *cred, int timeout, bool sleepLock) 211: session(ss), dbId(ssuid, path, NULL) 212{ 213 params.idleTimeout = timeout; 214 params.lockOnSleep = sleepLock; 215 dbRef = ss.createDb(dbId, cred, NULL, params); 216 detail("Database %s created", path); 217} 218 219 220void DbTester::unlock(const char *howWrong) 221{ 222 session.lock(dbRef); 223 try { 224 session.unlock(dbRef); 225 if (howWrong) 226 error("DATABASE MISTAKENLY UNLOCKED: %s", howWrong); 227 } catch (CssmError &err) { 228 if (!howWrong) 229 error(err, howWrong); 230 detail(err, howWrong); 231 } 232} 233 234void DbTester::changePassphrase(const AccessCredentials *cred, const char *howWrong) 235{ 236 session.lock(dbRef); 237 try { 238 session.changePassphrase(dbRef, cred); 239 if (howWrong) 240 error("PASSPHRASE CHANGE MISTAKENLY SUCCEEDED: %s", howWrong); 241 } catch (CssmError &err) { 242 if (!howWrong) 243 error(err, howWrong); 244 detail(err, howWrong); 245 } 246} 247