2 * dhTest - simple Diffie-Hellman exerciser.
6 #include <Security/cssm.h>
9 #include <security_cdsa_utils/cuFileIo.h>
12 #define USAGE_DEF "noUsage"
14 #define KEY_SIZE_DEF 512
15 #define DERIVE_KEY_SIZE 128
16 #define DERIVE_KEY_ALG CSSM_ALGID_AES
18 static void usage(char **argv
)
20 printf("usage: %s [options]\n", argv
[0]);
22 printf(" k=keySize (default = %d)\n", KEY_SIZE_DEF
);
23 printf(" l=loops (0=forever)\n");
24 printf(" p=pauseInterval (default=0, no pause)\n");
25 printf(" D (CSP/DL; default = bare CSP)\n");
26 printf(" o=fileName (dump key and param blobs to filename)\n");
27 printf(" i=filename (obtain param blobs from filename)\n");
28 printf(" 8 (private key in PKCS8 format, default is PKCS3)\n");
29 printf(" x (public key in X509 format, default is PKCS3)\n");
30 printf(" f (public key is ref form; default is raw)\n");
32 printf(" v(erbose))\n");
37 * Generate a Diffie-Hellman key pair. Optionally allows specification of
38 * algorithm parameters, and optionally returns algorithm parameters if
42 CSSM_CSP_HANDLE cspHand
,
45 const CSSM_DATA
*inParams
, // optional
46 CSSM_DATA_PTR outParams
, // optional, we malloc
48 CSSM_KEYBLOB_FORMAT privForm
,
49 CSSM_KEYBLOB_FORMAT pubForm
,
54 CSSM_CC_HANDLE ccHand
;
55 CSSM_DATA labelData
= { strlen(USAGE_DEF
), (uint8
*)USAGE_DEF
};
57 if(inParams
&& outParams
) {
58 printf("***dhKeyGen: inParams and outParams are mutually "
62 memset(pubKey
, 0, sizeof(CSSM_KEY
));
63 memset(privKey
, 0, sizeof(CSSM_KEY
));
65 crtn
= CSSM_CSP_CreateKeyGenContext(cspHand
,
72 inParams
, // Params, may be NULL
75 printError("CSSM_CSP_CreateKeyGenContext", crtn
);
76 return testError(quiet
);
79 if((inParams
== NULL
) && (outParams
!= NULL
)) {
80 /* explicitly generate params and return them to caller */
81 outParams
->Data
= NULL
;
82 outParams
->Length
= 0;
83 crtn
= CSSM_GenerateAlgorithmParams(ccHand
,
84 keySizeInBits
, outParams
);
86 printError("CSSM_GenerateAlgorithmParams", crtn
);
87 return testError(quiet
);
91 uint32 privAttr
= CSSM_KEYATTR_RETURN_REF
;
92 uint32 pubAttr
= CSSM_KEYATTR_RETURN_DATA
| CSSM_KEYATTR_EXTRACTABLE
;
93 if(privForm
!= CSSM_KEYBLOB_RAW_FORMAT_NONE
) {
94 crtn
= AddContextAttribute(ccHand
,
95 CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT
,
101 printError("AddContextAttribute(CSSM_ATTRIBUTE_PRIVATE_KEY"
105 privAttr
= CSSM_KEYATTR_RETURN_DATA
| CSSM_KEYATTR_EXTRACTABLE
;
108 pubAttr
= CSSM_KEYATTR_RETURN_REF
| CSSM_KEYATTR_EXTRACTABLE
;
110 else if(pubForm
!= CSSM_KEYBLOB_RAW_FORMAT_NONE
) {
111 crtn
= AddContextAttribute(ccHand
,
112 CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT
,
118 printError("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY"
123 crtn
= CSSM_GenerateKeyPair(ccHand
,
124 CSSM_KEYUSE_DERIVE
, // only legal use of a Diffie-Hellman key
128 /* private key specification */
131 &labelData
, // same labels
132 NULL
, // CredAndAclEntry
135 printError("CSSM_GenerateKeyPair", crtn
);
136 return testError(quiet
);
139 CSSM_DeleteContext(ccHand
);
144 * Perform Diffie-Hellman key exchange.
145 * Given "our" private key (in the form of a CSSM_KEY) and "their" public
146 * key (in the form of a raw blob of bytes), cook up a symmetric key.
148 static int dhKeyExchange(
149 CSSM_CSP_HANDLE cspHand
,
150 CSSM_KEY_PTR myPrivKey
,
151 CSSM_KEY_PTR theirPubKey
,
152 CSSM_KEY_PTR derivedKey
, // RETURNED
153 uint32 deriveKeySizeInBits
,
154 CSSM_ALGORITHMS derivedKeyAlg
,
155 uint32 derivedKeyUsage
,
156 uint32 derivedKeyAttr
,
160 CSSM_ACCESS_CREDENTIALS creds
;
161 CSSM_CC_HANDLE ccHand
;
162 CSSM_DATA labelData
= { strlen(USAGE_DEF
), (uint8
*)USAGE_DEF
};
164 memset(&creds
, 0, sizeof(CSSM_ACCESS_CREDENTIALS
));
165 memset(derivedKey
, 0, sizeof(CSSM_KEY
));
167 crtn
= CSSM_CSP_CreateDeriveKeyContext(cspHand
,
172 myPrivKey
, // BaseKey
178 printError("CSSM_CSP_CreateDeriveKeyContext", crtn
);
179 return testError(quiet
);
183 * Public key passed in as CSSM_DATA *Param - only if
184 * the pub key is in raw PKCS3 form
186 CSSM_DATA nullParam
= {0, NULL
};
187 CSSM_DATA_PTR paramPtr
;
188 CSSM_KEYHEADER
&hdr
= theirPubKey
->KeyHeader
;
189 if((hdr
.BlobType
== CSSM_KEYBLOB_RAW
) &&
190 (hdr
.Format
== CSSM_KEYBLOB_RAW_FORMAT_PKCS3
)) {
192 paramPtr
= &theirPubKey
->KeyData
;
195 /* add this pub key as a context attr */
196 crtn
= AddContextAttribute(ccHand
,
197 CSSM_ATTRIBUTE_PUBLIC_KEY
,
203 printError("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY)",
207 paramPtr
= &nullParam
;
209 crtn
= CSSM_DeriveKey(ccHand
,
217 printError("CSSM_DeriveKey", crtn
);
219 CSSM_DeleteContext(ccHand
);
224 CSSM_CSP_HANDLE cspHand
,
225 const CSSM_DATA
*inParams
, // optional
226 CSSM_DATA_PTR outParams
, // optional
227 uint32 keySizeInBits
,
228 CSSM_KEYBLOB_FORMAT privForm
,
229 CSSM_KEYBLOB_FORMAT pubForm
,
239 /* generate two key pairs */
253 /* note this MUST match the params either specified or generated in previous
255 if((inParams
== NULL
) && (outParams
== NULL
)) {
256 printf("***BRRZAP! Must provide a way to match D-H parameters!\n");
259 const CSSM_DATA
*theParams
= inParams
;
260 if(theParams
== NULL
) {
261 theParams
= outParams
;
276 /* derive two keys, ensure they match */
278 CSSM_KEY theirDerive
;
279 if(dhKeyExchange(cspHand
,
285 CSSM_KEYUSE_ENCRYPT
| CSSM_KEYUSE_DECRYPT
,
286 CSSM_KEYATTR_RETURN_DATA
| CSSM_KEYATTR_EXTRACTABLE
,
288 return testError(quiet
);
290 if(dhKeyExchange(cspHand
,
296 CSSM_KEYUSE_ENCRYPT
| CSSM_KEYUSE_DECRYPT
,
297 CSSM_KEYATTR_RETURN_DATA
| CSSM_KEYATTR_EXTRACTABLE
,
299 return testError(quiet
);
302 if(!appCompareCssmData(&myDerive
.KeyData
, &theirDerive
.KeyData
)) {
303 printf("***Key Exchange data miscompare***\n");
304 rtn
= testError(quiet
);
306 cspFreeKey(cspHand
, &myPub
);
307 cspFreeKey(cspHand
, &myPriv
);
308 cspFreeKey(cspHand
, &theirPub
);
309 cspFreeKey(cspHand
, &theirPriv
);
310 cspFreeKey(cspHand
, &myDerive
);
311 cspFreeKey(cspHand
, &theirDerive
);
315 int main(int argc
, char **argv
)
319 CSSM_CSP_HANDLE cspHand
;
322 CSSM_DATA inParams
= {0, NULL
};
323 CSSM_DATA outParams
= {0, NULL
};
324 CSSM_DATA_PTR inParamPtr
= NULL
;
325 CSSM_DATA_PTR outParamPtr
= NULL
;
327 /* user-spec'd parameters */
328 unsigned keySize
= KEY_SIZE_DEF
;
329 unsigned pauseInterval
= 0;
330 unsigned loops
= LOOPS_DEF
;
331 CSSM_BOOL quiet
= CSSM_FALSE
;
332 CSSM_BOOL verbose
= CSSM_FALSE
;
333 CSSM_BOOL bareCsp
= CSSM_TRUE
;
334 char *inFileName
= NULL
;
335 char *outFileName
= NULL
;
336 /* default: "use default blob form", i.e., PKCS3 */
337 CSSM_KEYBLOB_FORMAT privForm
= CSSM_KEYBLOB_RAW_FORMAT_NONE
;
338 CSSM_KEYBLOB_FORMAT pubForm
= CSSM_KEYBLOB_RAW_FORMAT_NONE
;
339 CSSM_BOOL pubIsRef
= CSSM_FALSE
;
341 for(arg
=1; arg
<argc
; arg
++) {
345 keySize
= atoi(&argp
[2]);
348 loops
= atoi(&argp
[2]);
351 pauseInterval
= atoi(&argp
[2]);
354 inFileName
= &argp
[2];
357 outFileName
= &argp
[2];
360 bareCsp
= CSSM_FALSE
;
363 privForm
= CSSM_KEYBLOB_RAW_FORMAT_PKCS8
;
366 pubForm
= CSSM_KEYBLOB_RAW_FORMAT_X509
;
369 pubIsRef
= CSSM_TRUE
;
382 /* Actually this test does NOT run with CSPDL */
384 printf("***%s does not run with CSPDL; aborting.\n", argv
[0]);
388 cspHand
= cspDlDbStartup(bareCsp
, NULL
);
393 /* optionally fetch algorithm parameters from a file */
396 int r
= readFile(inFileName
, &inParams
.Data
, &len
);
398 printf("***Can't read parameters from %s; aborting.\n",
402 inParams
.Length
= len
;
403 /* constant from now on */
404 inParamPtr
= &inParams
;
407 /* first time thru, no user-supplied parameters; generate them and
408 * save in outParams */
409 outParamPtr
= &outParams
;
411 printf("Starting dhTest; args: ");
412 for(i
=1; i
<argc
; i
++) {
413 printf("%s ", argv
[i
]);
416 for(loop
=1; ; loop
++) {
418 printf("...Loop %d\n", loop
);
420 i
= doTest(cspHand
, inParamPtr
, outParamPtr
, keySize
, privForm
,
421 pubForm
, pubIsRef
, quiet
);
426 /* first time thru */
428 /* save parameters for another run */
429 i
= writeFile(outFileName
, outParams
.Data
,
432 printf("***Error writing params to %s; continuing.\n",
437 printf("...wrote %lu bytes to %s\n",
438 outParams
.Length
, outFileName
);
443 /* from now on, use the parameters we just generated */
444 inParamPtr
= &outParams
;
446 /* and in any case don't fetch any more params */
449 if(loops
&& (loop
== loops
)) {
452 if(pauseInterval
&& ((loop
% pauseInterval
) == 0)) {
456 printf("Hit CR to proceed, q to quit: ");
463 CSSM_ModuleDetach(cspHand
);