2 * dsaPartial.cpp - test for partial DSA public handling
7 #include <Security/cssm.h>
8 #include <Security/cssmapple.h>
12 #include <security_cdsa_utils/cuFileIo.h>
13 #include "nssAppUtils.h"
16 * generate key pairs with one set of parameters, dsa1Priv and dsa1Pub;
17 * genenate another pair with a different set of params, dsa2Priv and
19 * manually cook up dsa1PubPartial from dsa1Pub;
20 * manually cook up dsa2PubPartial from dsa2Pub;
22 * with all legal and/or specified combos of {ref,raw} keys {
25 * vfy with dsa1PubPartial: CSSMERR_CSP_APPLE_DSA_PUBLIC_KEY_INCOMPLETE
26 * vfy with dsa1PubPartial and dsa1Pub (attrs)
27 * vfy with dsa2PubPartial and dsa1Pub (attrs) --> vfy fail
28 * vfy with dsa1PubPartial and dsa2Pub (attrs) --> vfy fail
29 * merge dsa1PubPartial + dsa1Pub --> merged;
30 * vfy with merged, should be good
31 * merge dsa1PubPartial + dsa2Pub -->merged;
32 * vfy with merged; vfy fail;
37 * Static parameter files.
39 * Regenerate these every once in a while with rsatool:
41 * # rsatool g a=d k=/tmp/foo M=dsaParam512_1.der
43 #define PARAMS_512_1 "dsaParam512_1.der"
44 #define PARAMS_512_2 "dsaParam512_2.der"
46 #define MAX_PTEXT_SIZE 512
47 #define KEY_ALG CSSM_ALGID_DSA
48 #define SIG_ALG CSSM_ALGID_SHA1WithDSA
50 #define KEY_SIZE_DEF 512
52 static void usage(char **argv
)
54 printf("Usage: %s [options]\n", argv
[0]);
57 printf(" p(ause on loop)\n");
59 printf(" v(erbose)\n");
60 printf(" D (CSPDL)\n");
61 printf(" r (all keys are raw)\n");
62 printf(" f (all keys are ref)\n");
67 * Generate DSA key pair with required alg parameters.
69 static CSSM_RETURN
genDsaKeyPair(
70 CSSM_CSP_HANDLE cspHand
,
71 uint32 keySize
, // in bits
72 CSSM_KEY_PTR pubKey
, // mallocd by caller
73 CSSM_BOOL pubIsRef
, // true - reference key, false - data
74 CSSM_KEY_PTR privKey
, // mallocd by caller
75 CSSM_BOOL privIsRef
, // true - reference key, false - data
76 const CSSM_DATA
*params
)
79 CSSM_CC_HANDLE ccHand
;
80 CSSM_DATA keyLabelData
;
85 return CSSMERR_CSSM_INVALID_POINTER
;
88 keyLabelData
.Data
= (uint8
*)"foobar",
89 keyLabelData
.Length
= 6;
90 memset(pubKey
, 0, sizeof(CSSM_KEY
));
91 memset(privKey
, 0, sizeof(CSSM_KEY
));
93 crtn
= CSSM_CSP_CreateKeyGenContext(cspHand
,
103 printError("CSSM_CSP_CreateKeyGenContext", crtn
);
107 /* cook up attribute bits */
109 pubAttr
= CSSM_KEYATTR_RETURN_REF
| CSSM_KEYATTR_EXTRACTABLE
;
112 pubAttr
= CSSM_KEYATTR_RETURN_DATA
| CSSM_KEYATTR_EXTRACTABLE
;
115 privAttr
= CSSM_KEYATTR_RETURN_REF
| CSSM_KEYATTR_EXTRACTABLE
;
118 privAttr
= CSSM_KEYATTR_RETURN_DATA
| CSSM_KEYATTR_EXTRACTABLE
;
121 crtn
= CSSM_GenerateKeyPair(ccHand
,
128 &keyLabelData
, // same labels
129 NULL
, // CredAndAclEntry
132 printError("CSSM_GenerateKeyPair", crtn
);
134 CSSM_DeleteContext(ccHand
);
140 * Create new public key by merging specified partial key and
141 * parameter-bearing key. All keys can be in any format (though
142 * it's the caller's responsibility to avoid using a ref paramKey
145 static CSSM_RETURN
dsaMergeParams(
146 CSSM_CSP_HANDLE cspHand
,
147 const CSSM_KEY
*partialKey
,
148 const CSSM_KEY
*paramKey
,
149 CSSM_KEY
&fullKey
, // RETURNED
150 bool fullIsRef
) // ref/raw
153 * First step is a null wrap or unwrap depending on
154 * format of partialKey.
156 CSSM_CC_HANDLE ccHand
;
158 CSSM_ACCESS_CREDENTIALS creds
;
159 CSSM_DATA label
= {10, (uint8
*)"dummyLabel"};
160 CSSM_DATA descrData
= {0, NULL
};
161 const CSSM_KEYHEADER
&hdr
= partialKey
->KeyHeader
;
163 memset(&creds
, 0, sizeof(CSSM_ACCESS_CREDENTIALS
));
164 crtn
= CSSM_CSP_CreateSymmetricContext(cspHand
,
168 NULL
, // wrapping key
174 printError("CSSM_CSP_CreateSymmetricContext", crtn
);
178 /* add in paramKey */
179 crtn
= AddContextAttribute(ccHand
,
180 CSSM_ATTRIBUTE_PARAM_KEY
,
186 printError("AddContextAttribute", crtn
);
192 memset(&targetKey
, 0, sizeof(targetKey
));
193 if(hdr
.BlobType
== CSSM_KEYBLOB_RAW
) {
194 /* raw --> ref : null unwrap */
195 crtn
= CSSM_UnwrapKey(ccHand
,
198 hdr
.KeyUsage
, // same as original
199 CSSM_KEYATTR_EXTRACTABLE
|CSSM_KEYATTR_RETURN_REF
,
201 NULL
, // CredAndAclEntry
203 &descrData
); // required
205 printError("dsaMergeParams CSSM_UnwrapKey (1)", crtn
);
210 /* ref --> raw : null wrap */
211 crtn
= CSSM_WrapKey(ccHand
,
214 NULL
, // DescriptiveData
217 printError("dsaMergeParams CSSM_WrapKey (1)", crtn
);
222 if(targetKey
.KeyHeader
.KeyAttr
& CSSM_KEYATTR_PARTIAL
) {
223 printf("***merged key still has CSSM_KEYATTR_PARTIAL\n");
224 return CSSMERR_CSSM_INTERNAL_ERROR
;
227 CSSM_KEYBLOB_TYPE targetBlob
;
229 targetBlob
= CSSM_KEYBLOB_REFERENCE
;
232 targetBlob
= CSSM_KEYBLOB_RAW
;
235 if(targetKey
.KeyHeader
.BlobType
== targetBlob
) {
238 CSSM_DeleteContext(ccHand
);
243 * We're going to reuse the context, but since the parameter merge
244 * has already been done, remove the CSSM_ATTRIBUTE_PARAM_KEY
247 CSSM_CONTEXT_ATTRIBUTE attr
;
248 memset(&attr
, 0, sizeof(attr
));
249 attr
.AttributeType
= CSSM_ATTRIBUTE_PARAM_KEY
;
250 crtn
= CSSM_DeleteContextAttributes(ccHand
, 1, &attr
);
252 printError("CSSM_DeleteContextAttributes", crtn
);
256 /* one more conversion */
257 if(targetBlob
== CSSM_KEYBLOB_REFERENCE
) {
258 /* raw --> ref : null unwrap */
259 crtn
= CSSM_UnwrapKey(ccHand
,
262 hdr
.KeyUsage
, // same as original
263 CSSM_KEYATTR_EXTRACTABLE
| CSSM_KEYATTR_RETURN_REF
,
265 NULL
, // CredAndAclEntry
267 &descrData
); // required
269 printError("dsaMergeParams CSSM_UnwrapKey (2)", crtn
);
274 /* ref --> raw : null wrap */
275 crtn
= CSSM_WrapKey(ccHand
,
278 NULL
, // DescriptiveData
281 printError("dsaMergeParams CSSM_WrapKey (2)", crtn
);
285 CSSM_FreeKey(cspHand
, NULL
, &targetKey
, CSSM_FALSE
);
286 CSSM_DeleteContext(ccHand
);
291 * Custom cspSigVerify with optional CSSM_ATTRIBUTE_PARAM_KEY
293 CSSM_RETURN
sigVerify(CSSM_CSP_HANDLE cspHand
,
294 uint32 algorithm
, // CSSM_ALGID_SHA1WithDSA, etc.
295 CSSM_KEY_PTR key
, // public key
296 CSSM_KEY_PTR paramKey
, // optional parameter key
297 const CSSM_DATA
*ptext
,
298 const CSSM_DATA
*sig
,
299 CSSM_RETURN expectResult
,
303 CSSM_CC_HANDLE sigHand
;
304 CSSM_RETURN ocrtn
= CSSM_OK
;
308 printf(" ...%s\n", op
);
310 crtn
= CSSM_CSP_CreateSignatureContext(cspHand
,
316 printError("CSSM_CSP_CreateSignatureContext", crtn
);
320 crtn
= AddContextAttribute(sigHand
,
321 CSSM_ATTRIBUTE_PARAM_KEY
,
327 printError("AddContextAttribute", crtn
);
331 crtn
= CSSM_VerifyData(sigHand
,
336 if(crtn
!= expectResult
) {
338 printf("%s: Unexpected good Sig Verify (expect %s)\n",
339 op
, cssmErrToStr(expectResult
));
340 ocrtn
= CSSMERR_CSSM_INTERNAL_ERROR
;
343 printError(op
, crtn
);
347 CSSM_DeleteContext(sigHand
);
352 CSSM_CSP_HANDLE cspHand
,
353 CSSM_KEY_PTR privKey_0
,
354 CSSM_KEY_PTR pubKeyBase_0
,
355 CSSM_KEY_PTR pubKeyPartial_0
,
356 CSSM_KEY_PTR pubKeyParam_0
, // full, raw format if CSPDL
357 CSSM_KEY_PTR pubKeyPartial_1
,
358 CSSM_KEY_PTR pubKeyParam_1
, // full, raw format if CSPDL
363 uint8 ptextBuf
[MAX_PTEXT_SIZE
];
364 CSSM_DATA ptext
= {0, ptextBuf
};
365 simpleGenData(&ptext
, 1, MAX_PTEXT_SIZE
);
366 CSSM_DATA sig
= {0, NULL
};
369 /* the single sign op for this routine */
370 crtn
= cspSign(cspHand
, SIG_ALG
, privKey_0
, &ptext
, &sig
);
372 return testError(quiet
);
375 /* normal verify with full key */
376 crtn
= sigVerify(cspHand
, SIG_ALG
, pubKeyBase_0
, NULL
,
377 &ptext
, &sig
, CSSM_OK
, "vfy with full key", verbose
);
379 return testError(quiet
);
382 /* good verify with partial key plus params */
383 crtn
= sigVerify(cspHand
, SIG_ALG
, pubKeyPartial_0
, pubKeyParam_0
,
384 &ptext
, &sig
, CSSM_OK
, "vfy with partial key and params",
387 if(testError(quiet
)) {
392 /* partial key failure */
393 crtn
= sigVerify(cspHand
, SIG_ALG
, pubKeyPartial_0
, NULL
,
395 CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE
,
396 "vfy with partial key no params", verbose
);
398 if(testError(quiet
)) {
403 /* partial key, wrong params */
404 crtn
= sigVerify(cspHand
, SIG_ALG
, pubKeyPartial_0
, pubKeyParam_1
,
406 CSSMERR_CSP_VERIFY_FAILED
,
407 "vfy with partial key wrong params", verbose
);
409 if(testError(quiet
)) {
414 /* wrong partial key, good params */
415 crtn
= sigVerify(cspHand
, SIG_ALG
, pubKeyPartial_1
, pubKeyParam_0
,
417 CSSMERR_CSP_VERIFY_FAILED
,
418 "vfy with wrong partial key, good params", verbose
);
420 if(testError(quiet
)) {
426 * Test merge via wrap/unwrap.
427 * First, a good merged key.
430 crtn
= dsaMergeParams(cspHand
,
436 return testError(quiet
);
438 crtn
= sigVerify(cspHand
, SIG_ALG
, &merged
, NULL
,
439 &ptext
, &sig
, CSSM_OK
, "vfy with good merged key", verbose
);
441 return testError(quiet
);
443 CSSM_FreeKey(cspHand
, NULL
, &merged
, CSSM_FALSE
);
445 /* now with a badly merged key (with the wrong params) */
446 crtn
= dsaMergeParams(cspHand
,
452 return testError(quiet
);
454 crtn
= sigVerify(cspHand
, SIG_ALG
, &merged
, NULL
,
456 CSSMERR_CSP_VERIFY_FAILED
,
457 "vfy with merged key wrong params", verbose
);
459 if(testError(quiet
)) {
463 CSSM_FreeKey(cspHand
, NULL
, &merged
, CSSM_FALSE
);
470 int main(int argc
, char **argv
)
473 CSSM_CSP_HANDLE cspHand
;
476 /* user spec'd variables */
477 unsigned loops
= LOOPS_DEF
;
478 CSSM_BOOL doPause
= CSSM_FALSE
;
479 CSSM_BOOL quiet
= CSSM_FALSE
;
480 CSSM_BOOL rawCSP
= CSSM_TRUE
;
481 CSSM_BOOL verbose
= CSSM_FALSE
;
482 uint32 keySize
= KEY_SIZE_DEF
;
483 CSSM_BOOL allRaw
= CSSM_FALSE
;
484 CSSM_BOOL allRef
= CSSM_FALSE
;
486 for(int arg
=1; arg
<argc
; arg
++) {
490 loops
= atoi(&argp
[2]);
515 if(!rawCSP
&& (allRaw
|| allRef
)) {
516 printf("CSPDL inconsistent with allRef and allRaw\n");
519 if(allRef
&& allRaw
) {
520 printf("allRef and allRaw are mutually exclusive\n");
524 /* read in params for two keypairs */
528 if(readFile(PARAMS_512_1
, (unsigned char **)¶ms1
.Data
, &len
)) {
529 printf("***Error reading %s. Aborting.\n", PARAMS_512_1
);
530 printf("***This test must be run from the cspxutils/dsaPartial directory.\n");
533 params1
.Length
= len
;
534 if(readFile(PARAMS_512_2
, (unsigned char **)¶ms2
.Data
, &len
)) {
535 printf("***Error reading %s. Aborting.\n", PARAMS_512_2
);
536 printf("***This test must be run from the cspxutils/dsaPartial directory.\n");
539 params2
.Length
= len
;
541 printf("Starting dsaPartial; args: ");
542 for(int i
=1; i
<argc
; i
++) {
543 printf("%s ", argv
[i
]);
546 cspHand
= cspDlDbStartup(rawCSP
, NULL
);
551 /* generate two keypairs */
558 printf("...generating keys...\n");
560 CSSM_BOOL genRefKeys
= CSSM_FALSE
;
561 if(!rawCSP
|| allRef
) {
562 genRefKeys
= CSSM_TRUE
;
564 crtn
= genDsaKeyPair(cspHand
, keySize
,
565 &dsa1Pub
, genRefKeys
,
566 &dsa1Priv
, genRefKeys
,
571 crtn
= genDsaKeyPair(cspHand
, keySize
,
572 &dsa2Pub
, genRefKeys
,
573 &dsa2Priv
, genRefKeys
,
579 /* CSPDL also requires separate raw parameter keys */
580 CSSM_KEY dsa1PubParam
;
581 CSSM_KEY dsa2PubParam
;
583 if(cspRefKeyToRaw(cspHand
, &dsa1Pub
, &dsa1PubParam
) ||
584 cspRefKeyToRaw(cspHand
, &dsa2Pub
, &dsa2PubParam
)) {
589 /* generate partial pub keys in raw form */
590 CSSM_KEY dsa1PubPartial
;
591 CSSM_KEY dsa2PubPartial
;
592 crtn
= extractDsaPartial(cspHand
, &dsa1Pub
, &dsa1PubPartial
);
596 crtn
= extractDsaPartial(cspHand
, &dsa2Pub
, &dsa2PubPartial
);
602 * Reference version of all 4 pub keys if we're going to mix & match
606 CSSM_KEY dsa1PubPartialRef
;
607 CSSM_KEY dsa2PubPartialRef
;
608 if(rawCSP
&& // CSPDL --> these were created as ref keys
609 !allRaw
&& // allRaw --> don't want ref keys
610 !allRef
) { // allRef --> these were created as ref keys
611 if(cspRawKeyToRef(cspHand
, &dsa1Pub
, &dsa1PubRef
) ||
612 cspRawKeyToRef(cspHand
, &dsa2Pub
, &dsa2PubRef
)) {
616 if(!rawCSP
|| !allRaw
) {
617 /* these were created in raw form unconditionally */
618 if(cspRawKeyToRef(cspHand
, &dsa1PubPartial
,
619 &dsa1PubPartialRef
) ||
620 cspRawKeyToRef(cspHand
, &dsa2PubPartial
,
621 &dsa2PubPartialRef
)) {
625 /* verify that these came back with the partial flag set */
626 if(!(dsa1PubPartialRef
.KeyHeader
.KeyAttr
&
627 CSSM_KEYATTR_PARTIAL
)) {
628 printf("***CSSM_KEYATTR_PARTIAL not set after null unwrap"
629 " of partial DSA key\n");
630 if(testError(quiet
)) {
634 if(!(dsa2PubPartialRef
.KeyHeader
.KeyAttr
&
635 CSSM_KEYATTR_PARTIAL
)) {
636 printf("***CSSM_KEYATTR_PARTIAL not set after null unwrap"
637 " of partial DSA key\n");
638 if(testError(quiet
)) {
645 for(unsigned loop
=0; loop
<loops
; loop
++) {
646 /* four pub keys - raw or ref */
647 CSSM_KEY_PTR pubKey_a
;
648 CSSM_KEY_PTR pubKey_b
;
649 CSSM_KEY_PTR pubKeyPartial_a
;
650 CSSM_KEY_PTR pubKeyPartial_b
;
654 /* raw CSP only - all ref keys */
655 /* base keys were generated as ref */
658 /* these alwasy generated as raw */
659 pubKeyPartial_a
= &dsa1PubPartialRef
;
660 pubKeyPartial_b
= &dsa2PubPartialRef
;
661 /* generated merged key ref too */
665 /* raw CSP only - all raw keys */
668 pubKeyPartial_a
= &dsa1PubPartial
;
669 pubKeyPartial_b
= &dsa2PubPartial
;
670 /* generated merged key ref too */
674 /* CSPDL - base keys are ref, partials are raw */
677 pubKeyPartial_a
= &dsa1PubPartialRef
;
678 pubKeyPartial_b
= &dsa2PubPartialRef
;
679 /* generated merged key ref too */
683 /* default: mix & match */
684 pubKey_a
= (loop
& 1) ? &dsa1Pub
: &dsa1PubRef
;
685 pubKey_b
= (loop
& 2) ? &dsa2Pub
: &dsa2PubRef
;
686 pubKeyPartial_a
= (loop
& 4) ?
687 &dsa1PubPartial
: &dsa1PubPartialRef
;
688 pubKeyPartial_b
= (loop
& 8) ?
689 &dsa2PubPartial
: &dsa2PubPartialRef
;
690 /* generated merged key different from partial_a*/
691 mergedIsRef
= (loop
& 2) ? true : false;
694 /* and two param keys - CSPDL requires raw, else the same as
695 * the "base" public key */
696 CSSM_KEY_PTR pubKeyParam_a
= pubKey_a
;
697 CSSM_KEY_PTR pubKeyParam_b
= pubKey_b
;
699 pubKeyParam_a
= &dsa1PubParam
;
700 pubKeyParam_b
= &dsa2PubParam
;
703 printf("...loop %u\n", loop
);
705 rtn
= doTest(cspHand
, &dsa1Priv
,
706 pubKey_a
, pubKeyPartial_a
, pubKeyParam_a
,
707 pubKeyPartial_b
, pubKeyParam_b
,
708 mergedIsRef
, quiet
, verbose
);
714 printf("Hit CR to proceed, q to quit: ");
715 char inch
= getchar();