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