2 * Copyright (c) 2000-2001,2011-2012,2014 Apple 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 * RSA_DSA_Keys.cpp - RSA, DSA related asymmetric key pair classes.
23 #include "RSA_DSA_keys.h"
24 #include <opensslUtils/opensslUtils.h>
25 #include <opensslUtils/opensslAsn1.h>
26 #include <security_cdsa_utilities/cssmdata.h>
27 #include <AppleCSPSession.h>
28 #include <AppleCSPUtils.h>
30 #include <security_utilities/debugging.h>
31 #include "RSA_DSA_utils.h"
32 #include <YarrowConnection.h>
33 #include <security_asn1/SecNssCoder.h>
35 #define RSA_PUB_EXPONENT 0x10001 /* recommended by RSA */
37 #define rsaKeyDebug(args...) secdebug("rsaKey", ## args)
41 *** RSA-style BinaryKey
44 /* constructor with optional existing RSA key */
45 /* FIXME how to transmit OAEP params? */
46 RSABinaryKey::RSABinaryKey(RSA
*rsaKey
)
49 mLabel(Allocator::standard())
53 RSABinaryKey::~RSABinaryKey()
61 void RSABinaryKey::setOaep(
62 const CSSM_DATA
&label
)
68 void RSABinaryKey::generateKeyBlob(
71 CSSM_KEYBLOB_FORMAT
&format
, /* IN/OUT */
72 AppleCSPSession
&session
,
73 const CssmKey
*paramKey
, /* optional, unused here */
74 CSSM_KEYATTR_FLAGS
&attrFlags
) /* IN/OUT */
79 /* FIXME get label from context here for OAEP */
82 * Here, the incoming default of CSSM_KEYBLOB_RAW_FORMAT_NONE
83 * is translated to our AppleCSP-custom defaults. App can override.
85 switch(mKeyHeader
.KeyClass
) {
86 case CSSM_KEYCLASS_PUBLIC_KEY
:
89 case CSSM_KEYBLOB_RAW_FORMAT_NONE
:
90 format
= RSA_PUB_KEY_FORMAT
; // default
92 case CSSM_KEYBLOB_RAW_FORMAT_DIGEST
:
94 /* have to take digest of the whole thing including label */
95 format
= CSSM_KEYBLOB_RAW_FORMAT_X509
;
98 /* calculate digest on PKCS1 blob */
99 format
= CSSM_KEYBLOB_RAW_FORMAT_PKCS1
;
102 case CSSM_KEYBLOB_RAW_FORMAT_PKCS1
:
103 case CSSM_KEYBLOB_RAW_FORMAT_X509
:
104 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH
:
105 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2
:
108 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_FORMAT
);
111 case CSSM_KEYCLASS_PRIVATE_KEY
:
114 case CSSM_KEYBLOB_RAW_FORMAT_NONE
: // default
115 format
= RSA_PRIV_KEY_FORMAT
;
117 case CSSM_KEYBLOB_RAW_FORMAT_DIGEST
:
119 /* have to take digest of the whole thing including label */
120 format
= CSSM_KEYBLOB_RAW_FORMAT_X509
;
123 /* calculate digest on PKCS1 blob */
124 format
= CSSM_KEYBLOB_RAW_FORMAT_PKCS1
;
128 case CSSM_KEYBLOB_RAW_FORMAT_PKCS1
:
129 case CSSM_KEYBLOB_RAW_FORMAT_PKCS8
:
130 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH
:
133 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_FORMAT
);
137 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
140 CssmAutoData
encodedKey(allocator
);
142 CSSM_DATA label
= mLabel
;
144 crtn
= RSAOAEPPublicKeyEncode(mRsaKey
, &label
, encodedKey
);
147 crtn
= RSAOAEPPrivateKeyEncode(mRsaKey
, &label
, encodedKey
);
152 crtn
= RSAPublicKeyEncode(mRsaKey
, format
, descData(), encodedKey
);
155 crtn
= RSAPrivateKeyEncode(mRsaKey
, format
, descData(), encodedKey
);
159 CssmError::throwMe(crtn
);
161 blob
= encodedKey
.release();
165 *** RSA-style AppleKeyPairGenContext
169 * This one is specified in, and called from, CSPFullPluginSession. Our
170 * only job is to prepare two subclass-specific BinaryKeys and call up to
171 * AppleKeyPairGenContext.
173 void RSAKeyPairGenContext::generate(
174 const Context
&context
,
178 RSABinaryKey
*pubBinKey
= new RSABinaryKey();
179 RSABinaryKey
*privBinKey
= new RSABinaryKey();
182 AppleKeyPairGenContext::generate(context
,
197 // this one is specified in, and called from, AppleKeyPairGenContext
198 void RSAKeyPairGenContext::generate(
199 const Context
&context
,
200 BinaryKey
&pubBinKey
,
201 BinaryKey
&privBinKey
,
205 * These casts throw exceptions if the keys are of the
206 * wrong classes, which would be a major bogon, since we created
207 * the keys in the above generate() function.
209 RSABinaryKey
&rPubBinKey
=
210 dynamic_cast<RSABinaryKey
&>(pubBinKey
);
211 RSABinaryKey
&rPrivBinKey
=
212 dynamic_cast<RSABinaryKey
&>(privBinKey
);
215 * One parameter from context: Key size in bits is required.
216 * FIXME - get public exponent from context?
218 keyBits
= context
.getInt(CSSM_ATTRIBUTE_KEY_LENGTH
,
219 CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH
);
220 if(keyBits
> rsaMaxKeySize()) {
221 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH
);
224 /* generate the private key */
225 rPrivBinKey
.mRsaKey
= RSA_generate_key(keyBits
,
229 if(rPrivBinKey
.mRsaKey
== NULL
) {
230 rsaKeyDebug("RSA_generate_key returned NULL");
231 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR
); // ???
234 /* public key is subset of private key */
235 rPubBinKey
.mRsaKey
= RSA_new();
236 if(rPrivBinKey
.mRsaKey
== NULL
) {
237 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR
);
239 RSA
*pub
= rPubBinKey
.mRsaKey
;
240 RSA
*priv
= rPrivBinKey
.mRsaKey
;
241 pub
->n
= BN_dup(priv
->n
);
242 pub
->e
= BN_dup(priv
->e
);
243 if((pub
->n
== NULL
) || (pub
->e
== NULL
)) {
244 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR
);
250 *** RSA-style CSPKeyInfoProvider.
252 RSAKeyInfoProvider::RSAKeyInfoProvider(
253 const CssmKey
&cssmKey
,
254 AppleCSPSession
&session
) :
255 CSPKeyInfoProvider(cssmKey
, session
)
259 CSPKeyInfoProvider
*RSAKeyInfoProvider::provider(
260 const CssmKey
&cssmKey
,
261 AppleCSPSession
&session
)
263 switch(cssmKey
.algorithm()) {
265 case CSSM_ALGMODE_PKCS1_EME_OAEP
:
270 switch(cssmKey
.keyClass()) {
271 case CSSM_KEYCLASS_PUBLIC_KEY
:
272 case CSSM_KEYCLASS_PRIVATE_KEY
:
277 /* OK, we'll handle this one */
278 return new RSAKeyInfoProvider(cssmKey
, session
);
281 /* Given a raw key, cook up a Binary key */
282 void RSAKeyInfoProvider::CssmKeyToBinary(
283 CssmKey
*paramKey
, // ignored
284 CSSM_KEYATTR_FLAGS
&attrFlags
, // IN/OUT, unused here
289 CSSM_DATA label
= {0, NULL
};
291 /* first cook up an RSA key */
292 rsaKey
= rawCssmKeyToRsa(mKey
, label
);
294 /* now drop that into a BinaryKey */
295 RSABinaryKey
*rsaBinKey
= new RSABinaryKey(rsaKey
);
298 rsaBinKey
->setOaep(label
);
304 * Obtain key size in bits.
306 void RSAKeyInfoProvider::QueryKeySizeInBits(
307 CSSM_KEY_SIZE
&keySize
)
310 CSSM_DATA label
= {0, NULL
};
312 if(mKey
.blobType() != CSSM_KEYBLOB_RAW
) {
313 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT
);
315 rsaKey
= rawCssmKeyToRsa(mKey
, label
);
316 keySize
.LogicalKeySizeInBits
= RSA_size(rsaKey
) * 8;
317 keySize
.EffectiveKeySizeInBits
= keySize
.LogicalKeySizeInBits
;
325 * Obtain blob suitable for hashing in CSSM_APPLECSP_KEYDIGEST
328 bool RSAKeyInfoProvider::getHashableBlob(
329 Allocator
&allocator
,
330 CssmData
&blob
) // blob to hash goes here
333 * The optimized case, a raw key in the "proper" format already.
334 * Only public keys in PKCS1 format fit this bill.
336 assert(mKey
.blobType() == CSSM_KEYBLOB_RAW
);
337 bool useAsIs
= false;
339 switch(mKey
.keyClass()) {
340 case CSSM_KEYCLASS_PUBLIC_KEY
:
341 if(mKey
.blobFormat() == CSSM_KEYBLOB_RAW_FORMAT_PKCS1
) {
345 case CSSM_KEYCLASS_PRIVATE_KEY
:
348 /* shouldn't be here */
350 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
);
353 const CssmData
&keyBlob
= CssmData::overlay(mKey
.KeyData
);
354 copyCssmData(keyBlob
, blob
, allocator
);
358 /* caller converts to binary and proceeds */
368 *** DSA-style BinaryKey
371 /* constructor with optional existing DSA key */
372 DSABinaryKey::DSABinaryKey(DSA
*dsaKey
)
377 DSABinaryKey::~DSABinaryKey()
385 void DSABinaryKey::generateKeyBlob(
386 Allocator
&allocator
,
388 CSSM_KEYBLOB_FORMAT
&format
,
389 AppleCSPSession
&session
,
390 const CssmKey
*paramKey
, /* optional */
391 CSSM_KEYATTR_FLAGS
&attrFlags
) /* IN/OUT */
397 * Here, the incoming default of CSSM_KEYBLOB_RAW_FORMAT_NONE
398 * is translated to our AppleCSP-custom defaults. App can override.
400 switch(mKeyHeader
.KeyClass
) {
401 case CSSM_KEYCLASS_PUBLIC_KEY
:
404 case CSSM_KEYBLOB_RAW_FORMAT_NONE
:
405 format
= DSA_PUB_KEY_FORMAT
; // default
407 case CSSM_KEYBLOB_RAW_FORMAT_FIPS186
:
408 case CSSM_KEYBLOB_RAW_FORMAT_X509
:
409 case CSSM_KEYBLOB_RAW_FORMAT_DIGEST
:
410 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2
:
413 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_FORMAT
);
416 case CSSM_KEYCLASS_PRIVATE_KEY
:
419 case CSSM_KEYBLOB_RAW_FORMAT_NONE
:
420 format
= DSA_PRIV_KEY_FORMAT
; // default
422 case CSSM_KEYBLOB_RAW_FORMAT_DIGEST
:
424 * This is calculated on the public key, which
425 * is not always part of a DSA private key's encoding...
426 * so first calculate the public key.
428 dsaKeyPrivToPub(mDsaKey
);
431 case CSSM_KEYBLOB_RAW_FORMAT_FIPS186
:
432 case CSSM_KEYBLOB_RAW_FORMAT_PKCS8
:
433 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL
:
436 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_FORMAT
);
440 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
443 /* possible conversion from partial binary key to fully
445 DSA
*dsaToEncode
= mDsaKey
;
446 DSA
*dsaUpgrade
= NULL
;
448 (mDsaKey
->p
== NULL
) &&
449 (paramKey
!= NULL
)) {
451 * Don't modify BinaryKey; make a copy.
453 dsaUpgrade
= DSA_new();
454 if(dsaUpgrade
== NULL
) {
455 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR
);
457 dsaUpgrade
->pub_key
= BN_dup(mDsaKey
->pub_key
);
458 crtn
= dsaGetParamsFromKey(dsaUpgrade
, *paramKey
, session
);
460 DSA_free(dsaUpgrade
);
461 CssmError::throwMe(crtn
);
464 /* success - switch keys and inform caller of attr change */
465 dsaToEncode
= dsaUpgrade
;
466 attrFlags
&= ~CSSM_KEYATTR_PARTIAL
;
470 * DSA private keys originating from BSAFE form - e.g., DSA private
471 * keys wrapped in a keychain (which have format FIPS186 by default)
472 * have no public key component. Generate the public key if we don't
475 if(!isPub
&& (dsaToEncode
->pub_key
== NULL
)) {
476 dsaKeyPrivToPub(dsaToEncode
);
479 CssmAutoData
encodedKey(allocator
);
481 crtn
= DSAPublicKeyEncode(dsaToEncode
, format
, descData(), encodedKey
);
484 crtn
= DSAPrivateKeyEncode(dsaToEncode
, format
, descData(), encodedKey
);
486 if(dsaUpgrade
!= NULL
) {
487 /* temp key, get rid of it */
488 DSA_free(dsaUpgrade
);
491 CssmError::throwMe(crtn
);
493 blob
= encodedKey
.release();
497 *** DSA-style AppleKeyPairGenContext
501 * This one is specified in, and called from, CSPFullPluginSession. Our
502 * only job is to prepare two subclass-specific BinaryKeys and call up to
503 * AppleKeyPairGenContext.
505 void DSAKeyPairGenContext::generate(
506 const Context
&context
,
510 DSABinaryKey
*pubBinKey
= new DSABinaryKey();
511 DSABinaryKey
*privBinKey
= new DSABinaryKey();
514 AppleKeyPairGenContext::generate(context
,
530 * This one is specified in, and called from, AppleKeyPairGenContext
532 void DSAKeyPairGenContext::generate(
533 const Context
&context
,
534 BinaryKey
&pubBinKey
,
535 BinaryKey
&privBinKey
,
539 * These casts throw exceptions if the keys are of the
540 * wrong classes, which would be a major bogon, since we created
541 * the keys in the above generate() function.
543 DSABinaryKey
&rPubBinKey
=
544 dynamic_cast<DSABinaryKey
&>(pubBinKey
);
545 DSABinaryKey
&rPrivBinKey
=
546 dynamic_cast<DSABinaryKey
&>(privBinKey
);
549 * Parameters from context:
550 * Key size in bits, required;
551 * {p,q,g} from generateParams, optional
553 keyBits
= context
.getInt(CSSM_ATTRIBUTE_KEY_LENGTH
,
554 CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH
);
555 if(keyBits
> DSA_MAX_KEY_SIZE
) {
556 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH
);
558 CssmData
*paramData
= context
.get
<CssmData
>(CSSM_ATTRIBUTE_ALG_PARAMS
);
560 NSS_DSAAlgParams algParams
;
561 SecNssCoder coder
; // generated algParams mallocd from here
562 if(paramData
!= NULL
) {
563 /* this contains the DER encoding of a NSS_DSAAlgParams */
564 CSSM_RETURN crtn
= DSADecodeAlgParams(algParams
, paramData
->Data
,
565 (unsigned)paramData
->Length
, coder
);
567 CssmError::throwMe(crtn
);
571 /* no alg params specified; generate them now using null (random) seed */
572 dsaGenParams(keyBits
, NULL
, 0, algParams
, coder
);
575 /* create key, stuff params into it */
576 rPrivBinKey
.mDsaKey
= DSA_new();
577 if(rPrivBinKey
.mDsaKey
== NULL
) {
578 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR
);
580 DSA
*dsaKey
= rPrivBinKey
.mDsaKey
;
581 dsaKey
->p
= cssmDataToBn(algParams
.p
);
582 dsaKey
->q
= cssmDataToBn(algParams
.q
);
583 dsaKey
->g
= cssmDataToBn(algParams
.g
);
585 /* generate the key (both public and private capabilities) */
586 int irtn
= DSA_generate_key(dsaKey
);
588 throwRsaDsa("DSA_generate_key");
591 /* public key is subset of private key */
592 rPubBinKey
.mDsaKey
= DSA_new();
593 if(rPrivBinKey
.mDsaKey
== NULL
) {
594 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR
);
596 DSA
*pub
= rPubBinKey
.mDsaKey
;
597 DSA
*priv
= rPrivBinKey
.mDsaKey
;
598 pub
->p
= BN_dup(priv
->p
);
599 pub
->q
= BN_dup(priv
->q
);
600 pub
->g
= BN_dup(priv
->g
);
601 pub
->pub_key
= BN_dup(priv
->pub_key
);
602 if((pub
->p
== NULL
) || (pub
->q
== NULL
) || (pub
->g
== NULL
) ||
603 (pub
->pub_key
== NULL
)) {
604 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR
);
609 * Generate keygen parameters, stash them in a context attr array for later use
610 * when actually generating the keys.
612 void DSAKeyPairGenContext::generate(
613 const Context
&context
,
617 Context::Attr
* &attrs
)
620 unsigned seedLen
= 0;
622 /* optional seed from context */
623 CssmData
*seedData
= context
.get
<CssmData
>(CSSM_ATTRIBUTE_SEED
);
625 seed
= seedData
->data();
626 seedLen
= (unsigned)seedData
->length();
629 /* generate the params, temp alloc from SecNssCoder */
630 NSS_DSAAlgParams algParams
;
632 dsaGenParams(bitSize
, seed
, seedLen
, algParams
, coder
);
635 * Here comes the fun part.
636 * We "return" the DER encoding of these generated params in two ways:
637 * 1. Copy out to app via the params argument, mallocing if Data ptr is NULL.
638 * The app must free this.
639 * 2. Cook up a 1-element Context::attr array containing one ALG_PARAM attr,
640 * a CSSM_DATA_PTR containing the DER encoding. We have to save a ptr to
641 * this attr array and free it, the CSSM_DATA it points to, and the DER
642 * encoding *that* points to, in our destructor.
646 CssmAutoData
aDerData(session());
647 DSAEncodeAlgParams(algParams
, aDerData
);
649 /* copy/release that into a mallocd CSSM_DATA. */
650 CSSM_DATA_PTR derData
= (CSSM_DATA_PTR
)session().malloc(sizeof(CSSM_DATA
));
651 *derData
= aDerData
.release();
653 /* stuff that into a one-element Attr array which we keep after returning */
655 mGenAttrs
= (Context::Attr
*)session().malloc(sizeof(Context::Attr
));
656 mGenAttrs
->AttributeType
= CSSM_ATTRIBUTE_ALG_PARAMS
;
657 mGenAttrs
->AttributeLength
= sizeof(CSSM_DATA
);
658 mGenAttrs
->Attribute
.Data
= derData
;
660 /* and "return" this stuff */
661 copyCssmData(CssmData::overlay(*derData
), params
, session());
666 /* free mGenAttrs and its referents if present */
667 void DSAKeyPairGenContext::freeGenAttrs()
669 if(mGenAttrs
== NULL
) {
672 if(mGenAttrs
->Attribute
.Data
) {
673 if(mGenAttrs
->Attribute
.Data
->Data
) {
674 session().free(mGenAttrs
->Attribute
.Data
->Data
);
676 session().free(mGenAttrs
->Attribute
.Data
);
678 session().free(mGenAttrs
);
682 * Generate DSA algorithm parameters from optional seed input, returning result
683 * into NSS_DSAAlgParamss.[pqg]. This is called from both GenerateParameters and from
684 * KeyPairGenerate (if no GenerateParameters has yet been called).
686 void DSAKeyPairGenContext::dsaGenParams(
687 uint32 keySizeInBits
,
688 const void *inSeed
, // optional
690 NSS_DSAAlgParams
&algParams
,
691 SecNssCoder
&coder
) // contents of algParams mallocd from here
693 unsigned char seedBuf
[SHA1_DIGEST_SIZE
];
696 /* validate key size */
697 if((keySizeInBits
< DSA_MIN_KEY_SIZE
) ||
698 (keySizeInBits
> DSA_MAX_KEY_SIZE
) ||
699 (keySizeInBits
& DSA_KEY_BITS_MASK
)) {
700 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH
);
703 /* seed from one of three sources */
705 /* 20 random seed bytes */
706 session().getRandomBytes(SHA1_DIGEST_SIZE
, seedBuf
);
709 else if(inSeedLen
== SHA1_DIGEST_SIZE
) {
711 seedPtr
= (void *)inSeed
;
714 /* hash caller's seed */
715 cspGenSha1Hash(inSeed
, inSeedLen
, seedBuf
);
719 DSA
*dsaKey
= DSA_generate_parameters(keySizeInBits
,
720 (unsigned char *)seedPtr
,
727 throwRsaDsa("DSA_generate_parameters");
730 /* stuff dsaKey->[pqg] into a caller's NSS_DSAAlgParams */
731 bnToCssmData(dsaKey
->p
, algParams
.p
, coder
);
732 bnToCssmData(dsaKey
->q
, algParams
.q
, coder
);
733 bnToCssmData(dsaKey
->g
, algParams
.g
, coder
);
739 *** DSA-style CSPKeyInfoProvider.
741 DSAKeyInfoProvider::DSAKeyInfoProvider(
742 const CssmKey
&cssmKey
,
743 AppleCSPSession
&session
) :
744 CSPKeyInfoProvider(cssmKey
, session
)
748 CSPKeyInfoProvider
*DSAKeyInfoProvider::provider(
749 const CssmKey
&cssmKey
,
750 AppleCSPSession
&session
)
752 switch(cssmKey
.algorithm()) {
758 switch(cssmKey
.keyClass()) {
759 case CSSM_KEYCLASS_PUBLIC_KEY
:
760 case CSSM_KEYCLASS_PRIVATE_KEY
:
765 /* OK, we'll handle this one */
766 return new DSAKeyInfoProvider(cssmKey
, session
);
769 /* Given a raw key, cook up a Binary key */
770 void DSAKeyInfoProvider::CssmKeyToBinary(
771 CssmKey
*paramKey
, // optional
772 CSSM_KEYATTR_FLAGS
&attrFlags
, // IN/OUT
778 /* first cook up an DSA key, then drop that into a BinaryKey */
779 dsaKey
= rawCssmKeyToDsa(mKey
, mSession
, paramKey
);
780 if(dsaKey
->p
== NULL
) {
781 attrFlags
|= CSSM_KEYATTR_PARTIAL
;
784 attrFlags
&= ~CSSM_KEYATTR_PARTIAL
;
786 DSABinaryKey
*dsaBinKey
= new DSABinaryKey(dsaKey
);
791 * Obtain key size in bits.
793 void DSAKeyInfoProvider::QueryKeySizeInBits(
794 CSSM_KEY_SIZE
&keySize
)
798 if(mKey
.blobType() != CSSM_KEYBLOB_RAW
) {
799 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT
);
801 dsaKey
= rawCssmKeyToDsa(mKey
,
803 NULL
); // no param key allowed here
804 if(dsaKey
->p
!= NULL
) {
805 /* normal fully-formed key */
806 keySize
.LogicalKeySizeInBits
= BN_num_bits(dsaKey
->p
);
807 keySize
.EffectiveKeySizeInBits
= keySize
.LogicalKeySizeInBits
;
811 /* partial key, get an approximation from pub_key */
812 keySize
.LogicalKeySizeInBits
= BN_num_bits(dsaKey
->pub_key
);
814 /* and indicate this anomaly like so */
815 CssmError::throwMe(CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE
);
820 * Obtain blob suitable for hashing in CSSM_APPLECSP_KEYDIGEST
823 bool DSAKeyInfoProvider::getHashableBlob(
824 Allocator
&allocator
,
825 CssmData
&blob
) // blob to hash goes here
827 /* No optimized case for DSA keys */