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