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...) secinfo("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 void RSAKeyPairGenContext::generate(const Context
&context
, uint32
, CssmData
¶ms
, uint32
&attrCount
, Context::Attr
* &attrs
) {
198 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED
);
201 // this one is specified in, and called from, AppleKeyPairGenContext
202 void RSAKeyPairGenContext::generate(
203 const Context
&context
,
204 BinaryKey
&pubBinKey
,
205 BinaryKey
&privBinKey
,
209 * These casts throw exceptions if the keys are of the
210 * wrong classes, which would be a major bogon, since we created
211 * the keys in the above generate() function.
213 RSABinaryKey
&rPubBinKey
=
214 dynamic_cast<RSABinaryKey
&>(pubBinKey
);
215 RSABinaryKey
&rPrivBinKey
=
216 dynamic_cast<RSABinaryKey
&>(privBinKey
);
219 * One parameter from context: Key size in bits is required.
220 * FIXME - get public exponent from context?
222 keyBits
= context
.getInt(CSSM_ATTRIBUTE_KEY_LENGTH
,
223 CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH
);
224 if(keyBits
> rsaMaxKeySize()) {
225 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH
);
228 /* generate the private key */
229 rPrivBinKey
.mRsaKey
= RSA_generate_key(keyBits
,
233 if(rPrivBinKey
.mRsaKey
== NULL
) {
234 rsaKeyDebug("RSA_generate_key returned NULL");
235 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR
); // ???
238 /* public key is subset of private key */
239 rPubBinKey
.mRsaKey
= RSA_new();
240 if(rPrivBinKey
.mRsaKey
== NULL
) {
241 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR
);
243 RSA
*pub
= rPubBinKey
.mRsaKey
;
244 RSA
*priv
= rPrivBinKey
.mRsaKey
;
245 pub
->n
= BN_dup(priv
->n
);
246 pub
->e
= BN_dup(priv
->e
);
247 if((pub
->n
== NULL
) || (pub
->e
== NULL
)) {
248 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR
);
254 *** RSA-style CSPKeyInfoProvider.
256 RSAKeyInfoProvider::RSAKeyInfoProvider(
257 const CssmKey
&cssmKey
,
258 AppleCSPSession
&session
) :
259 CSPKeyInfoProvider(cssmKey
, session
)
263 CSPKeyInfoProvider
*RSAKeyInfoProvider::provider(
264 const CssmKey
&cssmKey
,
265 AppleCSPSession
&session
)
267 switch(cssmKey
.algorithm()) {
269 case CSSM_ALGMODE_PKCS1_EME_OAEP
:
274 switch(cssmKey
.keyClass()) {
275 case CSSM_KEYCLASS_PUBLIC_KEY
:
276 case CSSM_KEYCLASS_PRIVATE_KEY
:
281 /* OK, we'll handle this one */
282 return new RSAKeyInfoProvider(cssmKey
, session
);
285 /* Given a raw key, cook up a Binary key */
286 void RSAKeyInfoProvider::CssmKeyToBinary(
287 CssmKey
*paramKey
, // ignored
288 CSSM_KEYATTR_FLAGS
&attrFlags
, // IN/OUT, unused here
293 CSSM_DATA label
= {0, NULL
};
295 /* first cook up an RSA key */
296 rsaKey
= rawCssmKeyToRsa(mKey
, label
);
298 /* now drop that into a BinaryKey */
299 RSABinaryKey
*rsaBinKey
= new RSABinaryKey(rsaKey
);
302 rsaBinKey
->setOaep(label
);
308 * Obtain key size in bits.
310 void RSAKeyInfoProvider::QueryKeySizeInBits(
311 CSSM_KEY_SIZE
&keySize
)
314 CSSM_DATA label
= {0, NULL
};
316 if(mKey
.blobType() != CSSM_KEYBLOB_RAW
) {
317 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT
);
319 rsaKey
= rawCssmKeyToRsa(mKey
, label
);
320 keySize
.LogicalKeySizeInBits
= RSA_size(rsaKey
) * 8;
321 keySize
.EffectiveKeySizeInBits
= keySize
.LogicalKeySizeInBits
;
329 * Obtain blob suitable for hashing in CSSM_APPLECSP_KEYDIGEST
332 bool RSAKeyInfoProvider::getHashableBlob(
333 Allocator
&allocator
,
334 CssmData
&blob
) // blob to hash goes here
337 * The optimized case, a raw key in the "proper" format already.
338 * Only public keys in PKCS1 format fit this bill.
340 assert(mKey
.blobType() == CSSM_KEYBLOB_RAW
);
341 bool useAsIs
= false;
343 switch(mKey
.keyClass()) {
344 case CSSM_KEYCLASS_PUBLIC_KEY
:
345 if(mKey
.blobFormat() == CSSM_KEYBLOB_RAW_FORMAT_PKCS1
) {
349 case CSSM_KEYCLASS_PRIVATE_KEY
:
352 /* shouldn't be here */
354 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
);
357 const CssmData
&keyBlob
= CssmData::overlay(mKey
.KeyData
);
358 copyCssmData(keyBlob
, blob
, allocator
);
362 /* caller converts to binary and proceeds */
372 *** DSA-style BinaryKey
375 /* constructor with optional existing DSA key */
376 DSABinaryKey::DSABinaryKey(DSA
*dsaKey
)
381 DSABinaryKey::~DSABinaryKey()
389 void DSABinaryKey::generateKeyBlob(
390 Allocator
&allocator
,
392 CSSM_KEYBLOB_FORMAT
&format
,
393 AppleCSPSession
&session
,
394 const CssmKey
*paramKey
, /* optional */
395 CSSM_KEYATTR_FLAGS
&attrFlags
) /* IN/OUT */
401 * Here, the incoming default of CSSM_KEYBLOB_RAW_FORMAT_NONE
402 * is translated to our AppleCSP-custom defaults. App can override.
404 switch(mKeyHeader
.KeyClass
) {
405 case CSSM_KEYCLASS_PUBLIC_KEY
:
408 case CSSM_KEYBLOB_RAW_FORMAT_NONE
:
409 format
= DSA_PUB_KEY_FORMAT
; // default
411 case CSSM_KEYBLOB_RAW_FORMAT_FIPS186
:
412 case CSSM_KEYBLOB_RAW_FORMAT_X509
:
413 case CSSM_KEYBLOB_RAW_FORMAT_DIGEST
:
414 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2
:
417 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_FORMAT
);
420 case CSSM_KEYCLASS_PRIVATE_KEY
:
423 case CSSM_KEYBLOB_RAW_FORMAT_NONE
:
424 format
= DSA_PRIV_KEY_FORMAT
; // default
426 case CSSM_KEYBLOB_RAW_FORMAT_DIGEST
:
428 * This is calculated on the public key, which
429 * is not always part of a DSA private key's encoding...
430 * so first calculate the public key.
432 dsaKeyPrivToPub(mDsaKey
);
435 case CSSM_KEYBLOB_RAW_FORMAT_FIPS186
:
436 case CSSM_KEYBLOB_RAW_FORMAT_PKCS8
:
437 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL
:
440 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_FORMAT
);
444 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
447 /* possible conversion from partial binary key to fully
449 DSA
*dsaToEncode
= mDsaKey
;
450 DSA
*dsaUpgrade
= NULL
;
452 (mDsaKey
->p
== NULL
) &&
453 (paramKey
!= NULL
)) {
455 * Don't modify BinaryKey; make a copy.
457 dsaUpgrade
= DSA_new();
458 if(dsaUpgrade
== NULL
) {
459 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR
);
461 dsaUpgrade
->pub_key
= BN_dup(mDsaKey
->pub_key
);
462 crtn
= dsaGetParamsFromKey(dsaUpgrade
, *paramKey
, session
);
464 DSA_free(dsaUpgrade
);
465 CssmError::throwMe(crtn
);
468 /* success - switch keys and inform caller of attr change */
469 dsaToEncode
= dsaUpgrade
;
470 attrFlags
&= ~CSSM_KEYATTR_PARTIAL
;
474 * DSA private keys originating from BSAFE form - e.g., DSA private
475 * keys wrapped in a keychain (which have format FIPS186 by default)
476 * have no public key component. Generate the public key if we don't
479 if(!isPub
&& (dsaToEncode
->pub_key
== NULL
)) {
480 dsaKeyPrivToPub(dsaToEncode
);
483 CssmAutoData
encodedKey(allocator
);
485 crtn
= DSAPublicKeyEncode(dsaToEncode
, format
, descData(), encodedKey
);
488 crtn
= DSAPrivateKeyEncode(dsaToEncode
, format
, descData(), encodedKey
);
490 if(dsaUpgrade
!= NULL
) {
491 /* temp key, get rid of it */
492 DSA_free(dsaUpgrade
);
495 CssmError::throwMe(crtn
);
497 blob
= encodedKey
.release();
501 *** DSA-style AppleKeyPairGenContext
505 * This one is specified in, and called from, CSPFullPluginSession. Our
506 * only job is to prepare two subclass-specific BinaryKeys and call up to
507 * AppleKeyPairGenContext.
509 void DSAKeyPairGenContext::generate(
510 const Context
&context
,
514 DSABinaryKey
*pubBinKey
= new DSABinaryKey();
515 DSABinaryKey
*privBinKey
= new DSABinaryKey();
518 AppleKeyPairGenContext::generate(context
,
534 * This one is specified in, and called from, AppleKeyPairGenContext
536 void DSAKeyPairGenContext::generate(
537 const Context
&context
,
538 BinaryKey
&pubBinKey
,
539 BinaryKey
&privBinKey
,
543 * These casts throw exceptions if the keys are of the
544 * wrong classes, which would be a major bogon, since we created
545 * the keys in the above generate() function.
547 DSABinaryKey
&rPubBinKey
=
548 dynamic_cast<DSABinaryKey
&>(pubBinKey
);
549 DSABinaryKey
&rPrivBinKey
=
550 dynamic_cast<DSABinaryKey
&>(privBinKey
);
553 * Parameters from context:
554 * Key size in bits, required;
555 * {p,q,g} from generateParams, optional
557 keyBits
= context
.getInt(CSSM_ATTRIBUTE_KEY_LENGTH
,
558 CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH
);
559 if(keyBits
> DSA_MAX_KEY_SIZE
) {
560 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH
);
562 CssmData
*paramData
= context
.get
<CssmData
>(CSSM_ATTRIBUTE_ALG_PARAMS
);
564 NSS_DSAAlgParams algParams
;
565 SecNssCoder coder
; // generated algParams mallocd from here
566 if(paramData
!= NULL
) {
567 /* this contains the DER encoding of a NSS_DSAAlgParams */
568 CSSM_RETURN crtn
= DSADecodeAlgParams(algParams
, paramData
->Data
,
569 (unsigned)paramData
->Length
, coder
);
571 CssmError::throwMe(crtn
);
575 /* no alg params specified; generate them now using null (random) seed */
576 dsaGenParams(keyBits
, NULL
, 0, algParams
, coder
);
579 /* create key, stuff params into it */
580 rPrivBinKey
.mDsaKey
= DSA_new();
581 if(rPrivBinKey
.mDsaKey
== NULL
) {
582 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR
);
584 DSA
*dsaKey
= rPrivBinKey
.mDsaKey
;
585 dsaKey
->p
= cssmDataToBn(algParams
.p
);
586 dsaKey
->q
= cssmDataToBn(algParams
.q
);
587 dsaKey
->g
= cssmDataToBn(algParams
.g
);
589 /* generate the key (both public and private capabilities) */
590 int irtn
= DSA_generate_key(dsaKey
);
592 throwRsaDsa("DSA_generate_key");
595 /* public key is subset of private key */
596 rPubBinKey
.mDsaKey
= DSA_new();
597 if(rPrivBinKey
.mDsaKey
== NULL
) {
598 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR
);
600 DSA
*pub
= rPubBinKey
.mDsaKey
;
601 DSA
*priv
= rPrivBinKey
.mDsaKey
;
602 pub
->p
= BN_dup(priv
->p
);
603 pub
->q
= BN_dup(priv
->q
);
604 pub
->g
= BN_dup(priv
->g
);
605 pub
->pub_key
= BN_dup(priv
->pub_key
);
606 if((pub
->p
== NULL
) || (pub
->q
== NULL
) || (pub
->g
== NULL
) ||
607 (pub
->pub_key
== NULL
)) {
608 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR
);
613 * Generate keygen parameters, stash them in a context attr array for later use
614 * when actually generating the keys.
616 void DSAKeyPairGenContext::generate(
617 const Context
&context
,
621 Context::Attr
* &attrs
)
624 unsigned seedLen
= 0;
626 /* optional seed from context */
627 CssmData
*seedData
= context
.get
<CssmData
>(CSSM_ATTRIBUTE_SEED
);
629 seed
= seedData
->data();
630 seedLen
= (unsigned)seedData
->length();
633 /* generate the params, temp alloc from SecNssCoder */
634 NSS_DSAAlgParams algParams
;
636 dsaGenParams(bitSize
, seed
, seedLen
, algParams
, coder
);
639 * Here comes the fun part.
640 * We "return" the DER encoding of these generated params in two ways:
641 * 1. Copy out to app via the params argument, mallocing if Data ptr is NULL.
642 * The app must free this.
643 * 2. Cook up a 1-element Context::attr array containing one ALG_PARAM attr,
644 * a CSSM_DATA_PTR containing the DER encoding. We have to save a ptr to
645 * this attr array and free it, the CSSM_DATA it points to, and the DER
646 * encoding *that* points to, in our destructor.
650 CssmAutoData
aDerData(session());
651 DSAEncodeAlgParams(algParams
, aDerData
);
653 /* copy/release that into a mallocd CSSM_DATA. */
654 CSSM_DATA_PTR derData
= (CSSM_DATA_PTR
)session().malloc(sizeof(CSSM_DATA
));
655 *derData
= aDerData
.release();
657 /* stuff that into a one-element Attr array which we keep after returning */
659 mGenAttrs
= (Context::Attr
*)session().malloc(sizeof(Context::Attr
));
660 mGenAttrs
->AttributeType
= CSSM_ATTRIBUTE_ALG_PARAMS
;
661 mGenAttrs
->AttributeLength
= sizeof(CSSM_DATA
);
662 mGenAttrs
->Attribute
.Data
= derData
;
664 /* and "return" this stuff */
665 copyCssmData(CssmData::overlay(*derData
), params
, session());
670 /* free mGenAttrs and its referents if present */
671 void DSAKeyPairGenContext::freeGenAttrs()
673 if(mGenAttrs
== NULL
) {
676 if(mGenAttrs
->Attribute
.Data
) {
677 if(mGenAttrs
->Attribute
.Data
->Data
) {
678 session().free(mGenAttrs
->Attribute
.Data
->Data
);
680 session().free(mGenAttrs
->Attribute
.Data
);
682 session().free(mGenAttrs
);
686 * Generate DSA algorithm parameters from optional seed input, returning result
687 * into NSS_DSAAlgParamss.[pqg]. This is called from both GenerateParameters and from
688 * KeyPairGenerate (if no GenerateParameters has yet been called).
690 void DSAKeyPairGenContext::dsaGenParams(
691 uint32 keySizeInBits
,
692 const void *inSeed
, // optional
694 NSS_DSAAlgParams
&algParams
,
695 SecNssCoder
&coder
) // contents of algParams mallocd from here
697 unsigned char seedBuf
[SHA1_DIGEST_SIZE
];
700 /* validate key size */
701 if((keySizeInBits
< DSA_MIN_KEY_SIZE
) ||
702 (keySizeInBits
> DSA_MAX_KEY_SIZE
) ||
703 (keySizeInBits
& DSA_KEY_BITS_MASK
)) {
704 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH
);
707 /* seed from one of three sources */
709 /* 20 random seed bytes */
710 session().getRandomBytes(SHA1_DIGEST_SIZE
, seedBuf
);
713 else if(inSeedLen
== SHA1_DIGEST_SIZE
) {
715 seedPtr
= (void *)inSeed
;
718 /* hash caller's seed */
719 cspGenSha1Hash(inSeed
, inSeedLen
, seedBuf
);
723 DSA
*dsaKey
= DSA_generate_parameters(keySizeInBits
,
724 (unsigned char *)seedPtr
,
731 throwRsaDsa("DSA_generate_parameters");
734 /* stuff dsaKey->[pqg] into a caller's NSS_DSAAlgParams */
735 bnToCssmData(dsaKey
->p
, algParams
.p
, coder
);
736 bnToCssmData(dsaKey
->q
, algParams
.q
, coder
);
737 bnToCssmData(dsaKey
->g
, algParams
.g
, coder
);
743 *** DSA-style CSPKeyInfoProvider.
745 DSAKeyInfoProvider::DSAKeyInfoProvider(
746 const CssmKey
&cssmKey
,
747 AppleCSPSession
&session
) :
748 CSPKeyInfoProvider(cssmKey
, session
)
752 CSPKeyInfoProvider
*DSAKeyInfoProvider::provider(
753 const CssmKey
&cssmKey
,
754 AppleCSPSession
&session
)
756 switch(cssmKey
.algorithm()) {
762 switch(cssmKey
.keyClass()) {
763 case CSSM_KEYCLASS_PUBLIC_KEY
:
764 case CSSM_KEYCLASS_PRIVATE_KEY
:
769 /* OK, we'll handle this one */
770 return new DSAKeyInfoProvider(cssmKey
, session
);
773 /* Given a raw key, cook up a Binary key */
774 void DSAKeyInfoProvider::CssmKeyToBinary(
775 CssmKey
*paramKey
, // optional
776 CSSM_KEYATTR_FLAGS
&attrFlags
, // IN/OUT
782 /* first cook up an DSA key, then drop that into a BinaryKey */
783 dsaKey
= rawCssmKeyToDsa(mKey
, mSession
, paramKey
);
784 if(dsaKey
->p
== NULL
) {
785 attrFlags
|= CSSM_KEYATTR_PARTIAL
;
788 attrFlags
&= ~CSSM_KEYATTR_PARTIAL
;
790 DSABinaryKey
*dsaBinKey
= new DSABinaryKey(dsaKey
);
795 * Obtain key size in bits.
797 void DSAKeyInfoProvider::QueryKeySizeInBits(
798 CSSM_KEY_SIZE
&keySize
)
802 if(mKey
.blobType() != CSSM_KEYBLOB_RAW
) {
803 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT
);
805 dsaKey
= rawCssmKeyToDsa(mKey
,
807 NULL
); // no param key allowed here
808 if(dsaKey
->p
!= NULL
) {
809 /* normal fully-formed key */
810 keySize
.LogicalKeySizeInBits
= BN_num_bits(dsaKey
->p
);
811 keySize
.EffectiveKeySizeInBits
= keySize
.LogicalKeySizeInBits
;
815 /* partial key, get an approximation from pub_key */
816 keySize
.LogicalKeySizeInBits
= BN_num_bits(dsaKey
->pub_key
);
818 /* and indicate this anomaly like so */
819 CssmError::throwMe(CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE
);
824 * Obtain blob suitable for hashing in CSSM_APPLECSP_KEYDIGEST
827 bool DSAKeyInfoProvider::getHashableBlob(
828 Allocator
&allocator
,
829 CssmData
&blob
) // blob to hash goes here
831 /* No optimized case for DSA keys */