2 * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
26 // Tester - test driver for securityserver client side.
28 #include "testclient.h"
29 #include "testutils.h"
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.
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?");
45 // set up dummy credentials
46 CssmKey dummyKey
; memset(&dummyKey
, 0, sizeof(dummyKey
));
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
),
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");
64 // retrieve the public key
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");
71 // make sure we can't retrieve the private key
72 CssmKey clearPrivateKey
;
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");
82 FakeContext
signContext(CSSM_ALGCLASS_SIGNATURE
, CSSM_ALGID_SHA1WithRSA
,
83 &::Context::Attr(CSSM_ATTRIBUTE_KEY
, dummyKey
),
85 ss
.generateSignature(signContext
, privateKey
, data
, signature
);
86 detail("Signature generated by SecurityServer");
88 // verify the signature (local)
90 Verify
verifier(csp
, CSSM_ALGID_SHA1WithRSA
);
91 verifier
.key(clearPublicKey
);
92 verifier
.verify(data
, signature
);
93 detail("Signature verified locally");
96 // verify the signature (SS)
97 ss
.verifySignature(signContext
, publicKey
, data
, signature
);
98 detail("Signature verified by SecurityServer");
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
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");
112 error(err
, "Unexpected exception on verify failure test");
122 printf("* DES encryption test\n");
123 ClientSession
ss(CssmAllocator::standard(), CssmAllocator::standard());
124 CSP
csp(gGuidAppleCSP
);
126 StringData
clearText("Insert witty quotation here.");
127 StringData
iv("abcdefgh");
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
);
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
);
146 size_t localLen
= localCrypt
.encrypt(clearText
, localCipher
, remData
);
148 error("LOCAL ENCRYPTION OVERFLOWED");
149 localCipher
.length(localLen
);
150 detail("Locally encrypted %ld bytes", localLen
);
153 CssmData unwrappedData
;
154 ResourceControlContext owner
;
155 FakeContext
unwrapContext(CSSM_ALGCLASS_SYMMETRIC
, CSSM_ALGID_NONE
, 0);
157 CssmKey::Header keyHeader
;
158 ss
.unwrapKey(noDb
, unwrapContext
, noKey
, noKey
,
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
);
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
),
173 CssmData remoteCipher
;
174 ss
.encrypt(cryptoContext
, keyRef
, clearText
, remoteCipher
);
175 detail("Plaintext encrypted on SecurityServer");
176 if (remoteCipher
== localCipher
)
177 detail("Ciphertexts verified");
179 error("CIPHERTEXTS DIFFER");
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");
188 error("PLAINTEXT MISMATCH");