1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 /*
21  * XSEC
22  *
23  * WinCAPICryptoKeyDSA := DSA Keys
24  *
25  * Author(s): Berin Lautenbach
26  *
27  * $Id: WinCAPICryptoKeyDSA.cpp 1817863 2017-12-11 22:47:43Z scantor $
28  *
29  */
30 
31 #include <xsec/enc/WinCAPI/WinCAPICryptoKeyDSA.hpp>
32 #include <xsec/enc/WinCAPI/WinCAPICryptoProvider.hpp>
33 #include <xsec/enc/XSCrypt/XSCryptCryptoBase64.hpp>
34 #include <xsec/enc/XSECCryptoException.hpp>
35 #include <xsec/enc/XSECCryptoUtils.hpp>
36 #include <xsec/framework/XSECError.hpp>
37 
38 #if defined (XSEC_HAVE_WINCAPI)
39 
40 #include <xercesc/util/Janitor.hpp>
41 
42 XSEC_USING_XERCES(ArrayJanitor);
43 
WinCAPICryptoKeyDSA(HCRYPTPROV prov)44 WinCAPICryptoKeyDSA::WinCAPICryptoKeyDSA(HCRYPTPROV prov) {
45 
46 	// Create a new key to be loaded as we go
47 
48 	m_key = 0;
49 	m_p = prov;
50 	m_keySpec = 0;
51 
52 	mp_P = NULL;
53 	mp_Q = NULL;
54 	mp_G = NULL;
55 	mp_Y = NULL;
56 
57 };
58 
59 // "Hidden" WinCAPI constructor
60 
WinCAPICryptoKeyDSA(HCRYPTPROV prov,HCRYPTKEY k)61 WinCAPICryptoKeyDSA::WinCAPICryptoKeyDSA(HCRYPTPROV prov,
62 										 HCRYPTKEY k) :
63 m_p(prov) {
64 
65 	m_key = k;		// NOTE - We OWN this handle
66 	m_keySpec = 0;
67 
68 	mp_P = mp_Q = mp_G = mp_Y = NULL;
69 	m_PLen = m_QLen = m_GLen = m_YLen = 0;
70 
71 }
72 
WinCAPICryptoKeyDSA(HCRYPTPROV prov,DWORD keySpec,bool isPrivate)73 WinCAPICryptoKeyDSA::WinCAPICryptoKeyDSA(HCRYPTPROV prov,
74 										 DWORD keySpec,
75 										 bool isPrivate) :
76 m_p(prov) {
77 
78 	if (isPrivate == false) {
79 
80 		throw XSECCryptoException(XSECCryptoException::DSAError,
81 			"Public keys defined via keySpec ctor not yet supported");
82 
83 
84 	}
85 
86 	m_key = 0;
87 	m_keySpec = keySpec;
88 
89 	mp_P = mp_Q = mp_G = mp_Y = NULL;
90 	m_PLen = m_QLen = m_GLen = m_YLen = 0;
91 
92 }
93 
~WinCAPICryptoKeyDSA()94 WinCAPICryptoKeyDSA::~WinCAPICryptoKeyDSA() {
95 
96 
97 	// If we have a DSA, delete it
98 
99 	if (m_key != 0)
100 		CryptDestroyKey(m_key);
101 
102 	if (mp_P != NULL)
103 		delete[] mp_P;
104 	if (mp_Q != NULL)
105 		delete[] mp_Q;
106 	if (mp_G != NULL)
107 		delete[] mp_G;
108 	if (mp_Y != NULL)
109 		delete[] mp_Y;
110 
111 };
112 
getProviderName() const113 const XMLCh * WinCAPICryptoKeyDSA::getProviderName() const {
114 	return DSIGConstants::s_unicodeStrPROVWinCAPI;
115 }
116 
117 // Generic key functions
118 
getKeyType() const119 XSECCryptoKey::KeyType WinCAPICryptoKeyDSA::getKeyType() const {
120 
121 	// Find out what we have
122 	if (m_key == NULL) {
123 
124 		// For now we don't really understand Private Windows keys
125 		if (m_keySpec != 0)
126 			return KEY_DSA_PRIVATE;
127 
128 		// Check if we have parameters loaded
129 		if (mp_P == NULL ||
130 			mp_Q == NULL ||
131 			mp_G == NULL ||
132 			mp_Y == NULL)
133 			return KEY_NONE;
134 		else
135 			return KEY_DSA_PUBLIC;
136 	}
137 
138 	if (m_keySpec != 0)
139 		return KEY_DSA_PAIR;
140 
141 	// If we have m_key - it must be public
142 
143 	return KEY_DSA_PUBLIC;
144 
145 }
146 
loadPBase64BigNums(const char * b64,unsigned int len)147 void WinCAPICryptoKeyDSA::loadPBase64BigNums(const char * b64, unsigned int len) {
148 
149 	if (mp_P != NULL) {
150 		delete[] mp_P;
151 		mp_P = NULL;		// In case we get an exception
152 	}
153 
154 	mp_P = WinCAPICryptoProvider::b642WinBN(b64, len, m_PLen);
155 
156 }
157 
loadQBase64BigNums(const char * b64,unsigned int len)158 void WinCAPICryptoKeyDSA::loadQBase64BigNums(const char * b64, unsigned int len) {
159 
160 	if (mp_Q != NULL) {
161 		delete[] mp_Q;
162 		mp_Q = NULL;		// In case we get an exception
163 	}
164 
165 	mp_Q = WinCAPICryptoProvider::b642WinBN(b64, len, m_QLen);
166 }
167 
loadGBase64BigNums(const char * b64,unsigned int len)168 void WinCAPICryptoKeyDSA::loadGBase64BigNums(const char * b64, unsigned int len) {
169 
170 	if (mp_G != NULL) {
171 		delete[] mp_G;
172 		mp_G = NULL;		// In case we get an exception
173 	}
174 
175 	mp_G = WinCAPICryptoProvider::b642WinBN(b64, len, m_GLen);
176 }
177 
loadYBase64BigNums(const char * b64,unsigned int len)178 void WinCAPICryptoKeyDSA::loadYBase64BigNums(const char * b64, unsigned int len) {
179 
180 	if (mp_Y != NULL) {
181 		delete[] mp_Y;
182 		mp_Y = NULL;		// In case we get an exception
183 	}
184 
185 	mp_Y = WinCAPICryptoProvider::b642WinBN(b64, len, m_YLen);
186 }
187 
loadJBase64BigNums(const char * b64,unsigned int len)188 void WinCAPICryptoKeyDSA::loadJBase64BigNums(const char * b64, unsigned int len) {
189 /*
190 	Do nothing
191 */
192 }
193 
194 
195 // --------------------------------------------------------------------------------
196 //           Verify a signature encoded as a Base64 string
197 // --------------------------------------------------------------------------------
198 
importKey(void) const199 void WinCAPICryptoKeyDSA::importKey(void) const {
200 
201 	if (m_key != 0 ||
202 		mp_P == NULL ||
203 		mp_Q == NULL ||
204 		mp_G == NULL ||
205 		mp_Y == NULL)
206 		return;
207 
208 	// Do some basic checks
209 	if ((m_QLen > 20) |
210 		(m_GLen > m_PLen) |
211 		(m_YLen > m_PLen)) {
212 
213 			throw XSECCryptoException(XSECCryptoException::DSAError,
214 				"WinCAPI:DSA - Parameter lengths inconsistent");
215 	}
216 
217 	// Create a DSS Public-Key blob
218 
219 	// First build a buffer to hold everything
220 	BYTE * blobBuffer;
221 	unsigned int blobBufferLen = WINCAPI_BLOBHEADERLEN + WINCAPI_DSSPUBKEYLEN + (3 * m_PLen) + 0x14 + WINCAPI_DSSSEEDLEN;
222 	XSECnew(blobBuffer, BYTE[blobBufferLen]);
223 	ArrayJanitor<BYTE> j_blobBuffer(blobBuffer);
224 
225 	// Blob header
226 	BLOBHEADER * header = (BLOBHEADER *) blobBuffer;
227 
228 	header->bType = PUBLICKEYBLOB;
229 	header->bVersion = 0x02;			// We are using a version 2 blob
230 	header->reserved = 0;
231 	header->aiKeyAlg = CALG_DSS_SIGN;
232 
233 	// Now the public key header
234 	DSSPUBKEY * pubkey = (DSSPUBKEY *) (blobBuffer + WINCAPI_BLOBHEADERLEN);
235 
236 	pubkey->magic = 0x31535344;		// ASCII encoding of DSS1
237 	pubkey->bitlen = m_PLen * 8;		// Number of bits in prime modulus
238 
239 	// Now copy in each of the keys
240 	BYTE * i = (BYTE *) (pubkey);
241 	i += WINCAPI_DSSPUBKEYLEN;
242 
243 	memcpy(i, mp_P, m_PLen);
244 	i+= m_PLen;
245 
246 	// Q
247 	memcpy(i, mp_Q, m_QLen);
248 	i += m_QLen;
249 
250 	// Pad with 0s
251 	unsigned int j;
252 	for (j = m_QLen; j < 20 ; ++j)
253 		*i++ = 0;
254 
255 	// Generator
256 	memcpy(i, mp_G, m_GLen);
257 	i += m_GLen;
258 	// Pad
259 	for (j = m_GLen; j < m_PLen ; ++j)
260 		*i++ = 0;
261 
262 	// Public key
263 	memcpy(i, mp_Y, m_YLen);
264 	i += m_YLen;
265 	// Pad
266 	for (j = m_YLen; j < m_PLen ; ++j)
267 		*i++ = 0;
268 
269 	// Set seed to 0
270 	for (j = 0; j < WINCAPI_DSSSEEDLEN; ++j)
271 		*i++ = 0xFF;	// SEED Counter set to 0xFFFFFFFF will cause seed to be ignored
272 
273 	// Now that we have the blob, import
274 	BOOL fResult = CryptImportKey(
275 					m_p,
276 					blobBuffer,
277 					blobBufferLen,
278 					0,				// Not signed
279 					0,				// No flags
280 					&m_key);
281 
282 	if (fResult == 0) {
283 
284 		throw XSECCryptoException(XSECCryptoException::DSAError,
285 			"WinCAPI:DSA Error attempting to import key parameters");
286 
287 	}
288 
289 }
290 
verifyBase64Signature(unsigned char * hashBuf,unsigned int hashLen,char * base64Signature,unsigned int sigLen) const291 bool WinCAPICryptoKeyDSA::verifyBase64Signature(unsigned char * hashBuf,
292 								 unsigned int hashLen,
293 								 char * base64Signature,
294 								 unsigned int sigLen) const {
295 
296 	// Use the currently loaded key to validate the Base64 encoded signature
297 
298 	if (m_key == 0) {
299 
300 		// Try to import from the parameters
301 		importKey();
302 
303 		if (m_key == 0) {
304 			throw XSECCryptoException(XSECCryptoException::DSAError,
305 				"WinCAPI:DSA - Attempt to validate signature with empty key");
306 		}
307 	}
308 
309 	// Decode the signature
310 	unsigned char * rawSig;
311 	DWORD rawSigLen;
312 	XSECnew(rawSig, BYTE [sigLen]);
313 	ArrayJanitor<BYTE> j_rawSig(rawSig);
314 
315 	// Decode the signature
316 	XSCryptCryptoBase64 b64;
317 
318 	b64.decodeInit();
319 	rawSigLen = b64.decode((unsigned char *) base64Signature, sigLen, rawSig, sigLen);
320 	rawSigLen += b64.decodeFinish(&rawSig[rawSigLen], sigLen - rawSigLen);
321 
322 	// Reverse the sig - Windows stores integers as octet streams in little endian
323 	// order.  The I2OSP algorithm used by XMLDSig to store integers is big endian
324 
325 	BYTE rawSigFinal[40];
326 	BYTE * j, *k, *l, *m;
327 
328 	unsigned char rb[20];
329 	unsigned char sb[20];
330 
331 	if (rawSigLen == 40) {
332 
333 		j = rawSig;
334 		k = rawSig + 20;
335 
336 	} else if (rawSigLen == 46 && ASN2DSASig(rawSig, rb, sb) == true) {
337 
338 		j = rb;
339 		k = sb;
340 
341 	} else {
342 
343 		throw XSECCryptoException(XSECCryptoException::DSAError,
344 			"WinCAPI:DSA::VerifyBase64Signature - Expect 40 bytes in a DSA signature");
345 	}
346 
347 	l = rawSigFinal + 19;
348 	m = rawSigFinal + 39;
349 
350 	while (l >= rawSigFinal) {
351 		*l-- = *j++;
352 		*m-- = *k++;
353 	}
354 
355 	// Have to create a Windows hash object and feed in the hash
356 	BOOL fResult;
357 	HCRYPTHASH h;
358 	fResult = CryptCreateHash(m_p,
359 					CALG_SHA1,
360 					0,
361 					0,
362 					&h);
363 
364 	if (!fResult) {
365 		throw XSECCryptoException(XSECCryptoException::DSAError,
366 			"WinCAPI:DSA - Error creating Windows Hash Object");
367 	}
368 
369 	// Feed the hash value into the newly created hash object
370 	fResult = CryptSetHashParam(
371 					h,
372 					HP_HASHVAL,
373 					hashBuf,
374 					0);
375 
376 	if (!fResult) {
377 		if (h)
378 			CryptDestroyHash(h);
379 		throw XSECCryptoException(XSECCryptoException::DSAError,
380 			"WinCAPI:DSA - Error Setting Hash Value in Windows Hash object");
381 	}
382 
383 	// Now validate
384 	fResult = CryptVerifySignature(
385 				h,
386 				rawSigFinal,
387 				40,
388 				m_key,
389 				NULL,
390 				0);
391 
392 	if (!fResult) {
393 
394 		DWORD error = GetLastError();
395 
396 		/* For some reason, the default Microsoft DSS provider generally returns
397 		 * NTE_FAIL (which denotes an internal failure in the provider) for a
398 		 * failed signature rather than NTE_BAD_SIGNATURE
399 		 */
400 
401 		if (error != NTE_BAD_SIGNATURE && error != NTE_FAIL) {
402 			if (h)
403 				CryptDestroyHash(h);
404 			throw XSECCryptoException(XSECCryptoException::DSAError,
405 			"WinCAPI:DSA - Error occurred in DSA validation");
406 		}
407 
408 		if (h)
409 			CryptDestroyHash(h);
410 		return false;
411 	}
412 
413 	if (h)
414 		CryptDestroyHash(h);
415 
416 	return true;
417 
418 }
419 
420 // --------------------------------------------------------------------------------
421 //           Sign and encode result as a Base64 string
422 // --------------------------------------------------------------------------------
423 
424 
signBase64Signature(unsigned char * hashBuf,unsigned int hashLen,char * base64SignatureBuf,unsigned int base64SignatureBufLen) const425 unsigned int WinCAPICryptoKeyDSA::signBase64Signature(unsigned char * hashBuf,
426 		unsigned int hashLen,
427 		char * base64SignatureBuf,
428 		unsigned int base64SignatureBufLen) const {
429 
430 	// Sign a pre-calculated hash using this key
431 
432 	if (m_keySpec == 0) {
433 
434 		throw XSECCryptoException(XSECCryptoException::DSAError,
435 			"WinCAPI:DSA - Attempt to sign data a public or non-existent key");
436 	}
437 
438 	// Have to create a Windows hash object and feed in the hash
439 	BOOL fResult;
440 	HCRYPTHASH h;
441 	fResult = CryptCreateHash(m_p,
442 					CALG_SHA1,
443 					0,
444 					0,
445 					&h);
446 
447 	if (!fResult) {
448 		throw XSECCryptoException(XSECCryptoException::DSAError,
449 			"WinCAPI:DSA - Error creating Windows Hash Object");
450 	}
451 
452 	// Feed the hash value into the newly created hash object
453 	fResult = CryptSetHashParam(
454 					h,
455 					HP_HASHVAL,
456 					hashBuf,
457 					0);
458 
459 	if (!fResult) {
460 		if (h)
461 			CryptDestroyHash(h);
462 		throw XSECCryptoException(XSECCryptoException::DSAError,
463 			"WinCAPI:DSA - Error Setting Hash Value in Windows Hash object");
464 	}
465 
466 	// Now sign
467 	BYTE rawSig[50];
468 	DWORD rawSigLen = 50;
469 	fResult = CryptSignHash(
470 				h,
471 				m_keySpec,
472 				NULL,
473 				0,
474 				rawSig,
475 				&rawSigLen);
476 
477 	if (!fResult || rawSigLen != 40) {
478 
479 		if (h)
480 			CryptDestroyHash(h);
481 		throw XSECCryptoException(XSECCryptoException::DSAError,
482 		"WinCAPI:DSA - Error occurred in DSA signing");
483 	}
484 
485 	if (h)
486 		CryptDestroyHash(h);
487 	// Now encode into a signature block
488 	BYTE rawSigFinal[40];
489 
490 	BYTE * i, * j, * m, * n;
491 
492 	i = rawSig;
493 	j = rawSig + 20;
494 	m = rawSigFinal + 19;
495 	n = rawSigFinal + 39;
496 
497 	while (m >= rawSigFinal) {
498 		*m-- = *i++;
499 		*n-- = *j++;
500 	}
501 
502 	// Now encode
503 	XSCryptCryptoBase64 b64;
504 	b64.encodeInit();
505 	unsigned int ret = b64.encode(rawSigFinal, 40, (unsigned char *) base64SignatureBuf, base64SignatureBufLen);
506 	ret += b64.encodeFinish((unsigned char *) &base64SignatureBuf[ret], base64SignatureBufLen - ret);
507 
508 	return ret;
509 
510 }
511 
512 // --------------------------------------------------------------------------------
513 //           Clone key
514 // --------------------------------------------------------------------------------
515 
516 
clone() const517 XSECCryptoKey * WinCAPICryptoKeyDSA::clone() const {
518 
519 	WinCAPICryptoKeyDSA * ret;
520 
521 	XSECnew(ret, WinCAPICryptoKeyDSA(m_p));
522 
523 	if (m_key != 0) {
524 
525 		// CryptDuplicateKey is not supported in Windows NT, so we need to export and then
526 		// reimport the key to get a copy
527 
528 		BYTE keyBuf[2048];
529 		DWORD keyBufLen = 2048;
530 		CryptExportKey(m_key, 0, PUBLICKEYBLOB, 0, keyBuf, &keyBufLen);
531 
532 		// Now re-import
533 		CryptImportKey(m_p, keyBuf, keyBufLen, NULL, 0, &ret->m_key);
534 	}
535 
536 	ret->m_PLen = m_PLen;
537 	if (mp_P != NULL) {
538 		XSECnew(ret->mp_P, BYTE[m_PLen]);
539 		memcpy(ret->mp_P, mp_P, m_PLen);
540 	}
541 	else
542 		ret->mp_P = NULL;
543 
544 	ret->m_QLen = m_QLen;
545 	if (mp_Q != NULL) {
546 		XSECnew(ret->mp_Q, BYTE[m_QLen]);
547 		memcpy(ret->mp_Q, mp_Q, m_QLen);
548 	}
549 	else
550 		ret->mp_Q = NULL;
551 
552 	ret->m_GLen = m_GLen;
553 	if (mp_G != NULL) {
554 		XSECnew(ret->mp_G, BYTE[m_GLen]);
555 		memcpy(ret->mp_G, mp_G, m_GLen);
556 	}
557 	else
558 		ret->mp_G = NULL;
559 
560 	ret->m_YLen = m_YLen;
561 	if (mp_Y != NULL) {
562 		XSECnew(ret->mp_Y, BYTE[m_YLen]);
563 		memcpy(ret->mp_Y, mp_Y, m_YLen);
564 	}
565 	else
566 		ret->mp_Y = NULL;
567 
568 
569 
570 	return ret;
571 
572 }
573 
574 // --------------------------------------------------------------------------------
575 //           Some utility functions
576 // --------------------------------------------------------------------------------
577 
loadParamsFromKey(void)578 void WinCAPICryptoKeyDSA::loadParamsFromKey(void) {
579 
580 	if (m_key == 0) {
581 
582 		if (m_keySpec == 0)
583 			return;
584 
585 		// See of we can get the user key
586 		if (!CryptGetUserKey(m_p, m_keySpec, &m_key))
587 			return;
588 
589 	}
590 
591 	// Export key into a keyblob
592 	BOOL fResult;
593 	DWORD blobLen;
594 
595 	fResult = CryptExportKey(
596 		m_key,
597 		0,
598 		PUBLICKEYBLOB,
599 		0,
600 		NULL,
601 		&blobLen);
602 
603 	if (fResult == 0 || blobLen < 1) {
604 		throw XSECCryptoException(XSECCryptoException::DSAError,
605 			"WinCAPI:DSA - Error exporting public key");
606 	}
607 
608 	BYTE * blob;
609 	XSECnew(blob, BYTE[blobLen]);
610 	ArrayJanitor<BYTE> j_blob(blob);
611 
612 	fResult = CryptExportKey(
613 		m_key,
614 		0,
615 		PUBLICKEYBLOB,
616 		0,
617 		blob,
618 		&blobLen);
619 
620 	if (fResult == 0 || blobLen < 1) {
621 		throw XSECCryptoException(XSECCryptoException::DSAError,
622 			"WinCAPI:DSA - Error exporting public key");
623 	}
624 
625 	DSSPUBKEY * pk = (DSSPUBKEY *) ( blob + WINCAPI_BLOBHEADERLEN );
626 	DWORD keyLen = pk->bitlen / 8;
627 
628 	// Copy the keys
629 
630 	BYTE * i = (BYTE *) ( pk );
631 	i += WINCAPI_DSSPUBKEYLEN;
632 	if (mp_P != NULL)
633 		delete[] mp_P;
634 
635 	XSECnew(mp_P, BYTE[keyLen]);
636 	memcpy(mp_P, i, keyLen);
637 	m_PLen = keyLen;
638 
639 	i+=keyLen;
640 
641 	if (mp_Q != NULL)
642 		delete[] mp_Q;
643 
644 	m_QLen = 20;
645 	while (i[m_QLen - 1] == 0 && m_QLen > 0)
646 		m_QLen--;
647 	XSECnew(mp_Q, BYTE[m_QLen]);
648 	memcpy(mp_Q, i, m_QLen);
649 
650 	i+=20;
651 
652 	if (mp_G != NULL)
653 		delete[] mp_G;
654 
655 	m_GLen = keyLen;
656 	while(i[m_GLen - 1] == 0 && m_GLen > 0)
657 		m_GLen--;
658 
659 	XSECnew(mp_G, BYTE[m_GLen]);
660 	memcpy(mp_G, i, m_GLen);
661 
662 	i+=keyLen;
663 
664 	if (mp_Y != NULL)
665 		delete[] mp_Y;
666 
667 	m_YLen = keyLen;
668 	while (i[m_YLen] == 0 && m_YLen > 0)
669 		m_YLen--;
670 
671 	XSECnew(mp_Y, BYTE[m_YLen]);
672 	memcpy(mp_Y, i, m_YLen);
673 
674 }
675 
getPBase64BigNums(char * b64,unsigned int len)676 unsigned int WinCAPICryptoKeyDSA::getPBase64BigNums(char * b64, unsigned int len) {
677 
678 	if (m_key == 0 && m_keySpec == 0 && mp_P == NULL) {
679 
680 		return 0;	// Nothing we can do
681 
682 	}
683 
684 	if (mp_P == NULL) {
685 
686 		loadParamsFromKey();
687 
688 	}
689 
690 	unsigned int bLen;
691 	unsigned char * b =  WinCAPICryptoProvider::WinBN2b64(mp_P, m_PLen, bLen);
692 	if (bLen > len)
693 		bLen = len;
694 	memcpy(b64, b, bLen);
695 	delete[] b;
696 
697 	return bLen;
698 
699 }
700 
getQBase64BigNums(char * b64,unsigned int len)701 unsigned int WinCAPICryptoKeyDSA::getQBase64BigNums(char * b64, unsigned int len) {
702 
703 	if (m_key == 0 && m_keySpec == 0 && mp_Q == NULL) {
704 
705 		return 0;	// Nothing we can do
706 
707 	}
708 
709 	if (mp_Q == NULL) {
710 
711 		loadParamsFromKey();
712 
713 	}
714 
715 	unsigned int bLen;
716 	unsigned char * b =  WinCAPICryptoProvider::WinBN2b64(mp_Q, m_QLen, bLen);
717 	if (bLen > len)
718 		bLen = len;
719 	memcpy(b64, b, bLen);
720 	delete[] b;
721 
722 	return bLen;
723 
724 }
725 
getGBase64BigNums(char * b64,unsigned int len)726 unsigned int WinCAPICryptoKeyDSA::getGBase64BigNums(char * b64, unsigned int len) {
727 
728 	if (m_key == 0 && m_keySpec == 0 && mp_G == NULL) {
729 
730 		return 0;	// Nothing we can do
731 
732 	}
733 
734 	if (mp_G == NULL) {
735 
736 		loadParamsFromKey();
737 
738 	}
739 
740 	unsigned int bLen;
741 	unsigned char * b =  WinCAPICryptoProvider::WinBN2b64(mp_G, m_GLen, bLen);
742 	if (bLen > len)
743 		bLen = len;
744 	memcpy(b64, b, bLen);
745 	delete[] b;
746 
747 	return bLen;
748 
749 }
750 
getYBase64BigNums(char * b64,unsigned int len)751 unsigned int WinCAPICryptoKeyDSA::getYBase64BigNums(char * b64, unsigned int len) {
752 
753 	if (m_key == 0 && m_keySpec == 0 && mp_Y == NULL) {
754 
755 		return 0;	// Nothing we can do
756 
757 	}
758 
759 	if (mp_Y == NULL) {
760 
761 		loadParamsFromKey();
762 
763 	}
764 
765 	unsigned int bLen;
766 	unsigned char * b =  WinCAPICryptoProvider::WinBN2b64(mp_Y, m_YLen, bLen);
767 	if (bLen > len)
768 		bLen = len;
769 	memcpy(b64, b, bLen);
770 	delete[] b;
771 
772 	return bLen;
773 
774 }
775 
776 #endif /* XSEC_HAVE_WINCAPI */
777 
778