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  * NSSCryptoKeyRSA := RSA Keys
24  *
25  * Author(s): Milan Tomic
26  *
27  */
28 
29 #include <xsec/enc/NSS/NSSCryptoKeyRSA.hpp>
30 #include <xsec/enc/NSS/NSSCryptoProvider.hpp>
31 #include <xsec/enc/XSCrypt/XSCryptCryptoBase64.hpp>
32 #include <xsec/enc/XSECCryptoException.hpp>
33 #include <xsec/framework/XSECError.hpp>
34 
35 #include <xercesc/util/Janitor.hpp>
36 
37 #if defined (XSEC_HAVE_NSS)
38 
39 #include <secder.h>
40 #include <secdig.h>
41 
42 XSEC_USING_XERCES(ArrayJanitor);
43 
44 // --------------------------------------------------------------------------------
45 //           Constructor
46 // --------------------------------------------------------------------------------
47 
NSSCryptoKeyRSA(SECKEYPublicKey * pubkey,SECKEYPrivateKey * privkey)48 NSSCryptoKeyRSA::NSSCryptoKeyRSA(SECKEYPublicKey * pubkey, SECKEYPrivateKey * privkey) {
49 
50   // NOTE - We OWN those handles
51   mp_pubkey   = pubkey;
52   mp_privkey  = privkey;
53 
54   mp_modulus  = NULL;
55   mp_exponent = NULL;
56 };
57 
58 // --------------------------------------------------------------------------------
59 //           Destructor
60 // --------------------------------------------------------------------------------
61 
~NSSCryptoKeyRSA()62 NSSCryptoKeyRSA::~NSSCryptoKeyRSA() {
63 
64   // Clean up
65 
66     if (mp_pubkey != 0)
67         SECKEY_DestroyPublicKey(mp_pubkey);
68 
69   if (mp_privkey != 0)
70         SECKEY_DestroyPrivateKey(mp_privkey);
71 
72     if (mp_modulus != NULL)
73          SECITEM_FreeItem(mp_modulus, PR_TRUE);
74 
75     if (mp_exponent != NULL)
76         SECITEM_FreeItem(mp_exponent, PR_TRUE);
77 };
78 
getProviderName() const79 const XMLCh * NSSCryptoKeyRSA::getProviderName() const {
80 	return DSIGConstants::s_unicodeStrPROVNSS;
81 }
82 
83 // --------------------------------------------------------------------------------
84 //           Get key type
85 // --------------------------------------------------------------------------------
86 
getKeyType() const87 XSECCryptoKey::KeyType NSSCryptoKeyRSA::getKeyType() const {
88 
89     // Find out what we have
90     if (mp_pubkey == 0) {
91 
92         if (mp_privkey != 0)
93             return KEY_RSA_PRIVATE;
94 
95         if (mp_exponent == NULL || mp_modulus == NULL)
96             return KEY_NONE;
97         else
98             return KEY_RSA_PUBLIC;
99 
100     }
101 
102     if (mp_privkey != 0)
103         return KEY_RSA_PAIR;
104 
105     return KEY_RSA_PUBLIC;
106 }
107 
108 
109 // --------------------------------------------------------------------------------
110 //           Load modulus
111 // --------------------------------------------------------------------------------
112 
loadPublicModulusBase64BigNums(const char * b64,unsigned int len)113 void NSSCryptoKeyRSA::loadPublicModulusBase64BigNums(const char* b64, unsigned int len) {
114 
115     if (mp_modulus != NULL) {
116 
117         SECITEM_FreeItem(mp_modulus, PR_TRUE);
118         mp_modulus = NULL;        // In case we get an exception
119 
120     }
121 
122   mp_modulus = NSSCryptoProvider::b642SI(b64, len);
123 
124 }
125 
126 // --------------------------------------------------------------------------------
127 //           Load exponent
128 // --------------------------------------------------------------------------------
129 
loadPublicExponentBase64BigNums(const char * b64,unsigned int len)130 void NSSCryptoKeyRSA::loadPublicExponentBase64BigNums(const char* b64, unsigned int len) {
131 
132     if (mp_exponent != NULL) {
133 
134         SECITEM_FreeItem(mp_exponent, PR_TRUE);
135         mp_exponent = NULL;        // In case we get an exception
136 
137     }
138 
139   mp_exponent = NSSCryptoProvider::b642SI(b64, len);
140 
141 }
142 
143 // --------------------------------------------------------------------------------
144 //           Import key
145 // --------------------------------------------------------------------------------
146 
importKey() const147 void NSSCryptoKeyRSA::importKey() const {
148 
149     if (mp_pubkey != 0 || mp_exponent == NULL || mp_modulus == NULL)
150         return;
151 
152 
153   PRArenaPool * arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
154 
155   if(arena == NULL) {
156 
157       throw XSECCryptoException(XSECCryptoException::GeneralError,
158               "NSS:RSA Error attempting create new arena");
159 
160   }
161 
162   mp_pubkey = (SECKEYPublicKey*)PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
163 
164   if(mp_pubkey == NULL ) {
165 
166       PORT_FreeArena(arena, PR_FALSE);
167 
168       throw XSECCryptoException(XSECCryptoException::GeneralError,
169               "NSS:RSA Error attempting create new arena");
170 
171   }
172 
173   mp_pubkey->arena = arena;
174   mp_pubkey->keyType = rsaKey;
175 
176   SECStatus s = SECITEM_CopyItem(arena, &(mp_pubkey->u.rsa.modulus), mp_modulus);
177 
178   if (s != SECSuccess) {
179 
180     PORT_FreeArena(arena, PR_FALSE);
181 
182     throw XSECCryptoException(XSECCryptoException::DSAError,
183           "NSS:RSA Error attempting to import modulus");
184 
185   }
186 
187   s = SECITEM_CopyItem(arena, &(mp_pubkey->u.rsa.publicExponent), mp_exponent);
188 
189   if (s != SECSuccess) {
190 
191     PORT_FreeArena(arena, PR_FALSE);
192 
193     throw XSECCryptoException(XSECCryptoException::DSAError,
194           "NSS:RSA Error attempting to import exponent");
195 
196   }
197 
198 }
199 
200 // --------------------------------------------------------------------------------
201 //           Verify a signature encoded as a Base64 string
202 // --------------------------------------------------------------------------------
203 
verifySHA1PKCS1Base64Signature(const unsigned char * hashBuf,unsigned int hashLen,const char * base64Signature,unsigned int sigLen,XSECCryptoHash::HashType type) const204 bool NSSCryptoKeyRSA::verifySHA1PKCS1Base64Signature(const unsigned char * hashBuf,
205                                  unsigned int hashLen,
206                                  const char * base64Signature,
207                                  unsigned int sigLen,
208                                  XSECCryptoHash::HashType type) const {
209 
210     // Use the currently loaded key to validate the Base64 encoded signature
211 
212     if (mp_pubkey == 0) {
213 
214       // Try to import from the parameters
215           importKey();
216 
217       if (mp_pubkey == 0) {
218           throw XSECCryptoException(XSECCryptoException::RSAError,
219                 "NSS:RSA - Attempt to validate signature with empty key");
220       }
221     }
222 
223     // Decode the signature
224     unsigned char * rawSig;
225     unsigned int rawSigLen;
226     XSECnew(rawSig, unsigned char[sigLen]);
227     ArrayJanitor<unsigned char> j_rawSig(rawSig);
228 
229     // Decode the signature
230     XSCryptCryptoBase64 b64;
231 
232     b64.decodeInit();
233     rawSigLen = b64.decode((unsigned char *) base64Signature, sigLen, rawSig, sigLen);
234     rawSigLen += b64.decodeFinish(&rawSig[rawSigLen], sigLen - rawSigLen);
235 
236   SECItem signature;
237   signature.type = siBuffer;
238   signature.data = rawSig;
239   signature.len = rawSigLen;
240 
241   SECItem data;
242   data.data = 0;
243   data.len = 0;
244   SECOidTag hashalg;
245   PRArenaPool * arena = 0;
246   SGNDigestInfo *di = 0;
247   SECItem * res;
248 
249   switch (type) {
250 
251   case (XSECCryptoHash::HASH_MD5):
252       hashalg = SEC_OID_MD5;
253       break;
254   case (XSECCryptoHash::HASH_SHA1):
255       hashalg = SEC_OID_SHA1;
256       break;
257   case (XSECCryptoHash::HASH_SHA256):
258       hashalg = SEC_OID_SHA256;
259       break;
260   case (XSECCryptoHash::HASH_SHA384):
261       hashalg = SEC_OID_SHA384;
262       break;
263   case (XSECCryptoHash::HASH_SHA512):
264       hashalg = SEC_OID_SHA512;
265       break;
266   default:
267       throw XSECCryptoException(XSECCryptoException::RSAError,
268           "NSS:RSA - Unsupported hash algorithm in RSA sign");
269   }
270 
271   arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
272   if (!arena) {
273       throw XSECCryptoException(XSECCryptoException::RSAError,
274           "NSS:RSA - Error creating arena");
275   }
276 
277   di = SGN_CreateDigestInfo(hashalg, (unsigned char * )hashBuf, hashLen);
278   if (di == NULL) {
279 
280       PORT_FreeArena(arena, PR_FALSE);
281 
282       throw XSECCryptoException(XSECCryptoException::RSAError,
283           "NSS:RSA - Error creating digest info");
284   }
285 
286       res = SEC_ASN1EncodeItem(arena, &data, di, NSS_Get_sgn_DigestInfoTemplate(NULL, 0));
287 
288       if (!res) {
289       SGN_DestroyDigestInfo(di);
290       PORT_FreeArena(arena, PR_FALSE);
291 
292       throw XSECCryptoException(XSECCryptoException::RSAError,
293           "NSS:RSA - Error encoding digest info for RSA sign");
294       }
295 
296     // Verify signature
297     SECStatus s = PK11_Verify(mp_pubkey, &signature, &data, NULL);
298 
299     return s == SECSuccess;
300 }
301 
302 // --------------------------------------------------------------------------------
303 //           Sign and encode result as a Base64 string
304 // --------------------------------------------------------------------------------
305 
signSHA1PKCS1Base64Signature(unsigned char * hashBuf,unsigned int hashLen,char * base64SignatureBuf,unsigned int base64SignatureBufLen,XSECCryptoHash::HashType type) const306 unsigned int NSSCryptoKeyRSA::signSHA1PKCS1Base64Signature(unsigned char * hashBuf,
307         unsigned int hashLen,
308         char * base64SignatureBuf,
309         unsigned int base64SignatureBufLen,
310         XSECCryptoHash::HashType type) const {
311 
312     // Sign a pre-calculated hash using this key
313     if (mp_privkey == 0) {
314         throw XSECCryptoException(XSECCryptoException::RSAError,
315             "NSS:RSA - Attempt to sign data using a public or un-loaded key");
316     }
317 
318     unsigned char * rawSig;
319     XSECnew(rawSig, unsigned char[base64SignatureBufLen]);
320     ArrayJanitor<unsigned char> j_rawSig(rawSig);
321 
322     SECItem signature;
323     signature.type = siBuffer;
324     signature.data = rawSig;
325     signature.len = base64SignatureBufLen;
326 
327     SECItem data;
328     data.data = 0;
329     SECOidTag hashalg;
330     PRArenaPool * arena = 0;
331     SGNDigestInfo *di = 0;
332     SECItem * res;
333 
334     switch (type) {
335 
336     case (XSECCryptoHash::HASH_MD5):
337         hashalg = SEC_OID_MD5;
338         break;
339     case (XSECCryptoHash::HASH_SHA1):
340         hashalg = SEC_OID_SHA1;
341         break;
342     case (XSECCryptoHash::HASH_SHA256):
343         hashalg = SEC_OID_SHA256;
344         break;
345     case (XSECCryptoHash::HASH_SHA384):
346         hashalg = SEC_OID_SHA384;
347         break;
348     case (XSECCryptoHash::HASH_SHA512):
349         hashalg = SEC_OID_SHA512;
350         break;
351     default:
352         throw XSECCryptoException(XSECCryptoException::RSAError,
353             "NSS:RSA - Unsupported hash algorithm in RSA sign");
354     }
355 
356     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
357     if (!arena) {
358         throw XSECCryptoException(XSECCryptoException::RSAError,
359             "NSS:RSA - Error creating arena");
360     }
361 
362     di = SGN_CreateDigestInfo(hashalg, hashBuf, hashLen);
363     if (di == NULL) {
364         PORT_FreeArena(arena, PR_FALSE);
365 
366         throw XSECCryptoException(XSECCryptoException::RSAError,
367             "NSS:RSA - Error creating digest info");
368     }
369 
370     res = SEC_ASN1EncodeItem(arena, &data, di, NSS_Get_sgn_DigestInfoTemplate(NULL, 0));
371 
372     if (!res) {
373         SGN_DestroyDigestInfo(di);
374         PORT_FreeArena(arena, PR_FALSE);
375 
376         throw XSECCryptoException(XSECCryptoException::RSAError,
377             "NSS:RSA - Error encoding digest info for RSA sign");
378     }
379 
380 /*    data.type = siBuffer;
381     data.data = hashBuf;
382     data.len = hashLen;*/
383 
384     /* As of V1.3.1 - create a DigestInfo block */
385 
386 
387     SECStatus s = PK11_Sign(mp_privkey, &signature, &data);
388 
389     SGN_DestroyDigestInfo(di);
390     PORT_FreeArena(arena, PR_FALSE);
391 
392     if (s != SECSuccess) {
393         throw XSECCryptoException(XSECCryptoException::RSAError,
394             "NSS:RSA - Error during signing operation");
395     }
396 
397     // Now encode
398     XSCryptCryptoBase64 b64;
399     b64.encodeInit();
400     unsigned int ret = b64.encode(signature.data, signature.len, (unsigned char *) base64SignatureBuf, base64SignatureBufLen);
401     ret += b64.encodeFinish((unsigned char *) &base64SignatureBuf[ret], base64SignatureBufLen - ret);
402 
403     return ret;
404 }
405 
406 // --------------------------------------------------------------------------------
407 //           Clone key
408 // --------------------------------------------------------------------------------
409 
clone() const410 XSECCryptoKey * NSSCryptoKeyRSA::clone() const {
411 
412     NSSCryptoKeyRSA * ret;
413 
414     XSECnew(ret, NSSCryptoKeyRSA(mp_pubkey, mp_privkey));
415 
416     if (mp_pubkey != 0) {
417         ret->mp_pubkey = SECKEY_CopyPublicKey(mp_pubkey);
418         if (ret->mp_pubkey == 0) {
419             throw XSECCryptoException(XSECCryptoException::MemoryError,
420                     "NSS:RSA Error attempting to clone (copy) public key");
421         }
422     }
423 
424     if (mp_privkey != 0) {
425         ret->mp_privkey = SECKEY_CopyPrivateKey(mp_privkey);
426         if (ret->mp_privkey == 0) {
427             throw XSECCryptoException(XSECCryptoException::MemoryError,
428                     "NSS:RSA Error attempting to clone (copy) private key");
429         }
430     }
431 
432     // Clone modulus
433     if (mp_modulus != 0) {
434         ret->mp_modulus = SECITEM_DupItem(mp_modulus);
435         if (ret->mp_modulus == 0) {
436             throw XSECCryptoException(XSECCryptoException::MemoryError,
437                     "NSS:RSA Error attempting to clone (copy) modulus");
438         }
439     }
440 
441     // Clone exponent
442     if (mp_exponent != 0) {
443         ret->mp_exponent = SECITEM_DupItem(mp_exponent);
444         if (ret->mp_exponent == 0) {
445             throw XSECCryptoException(XSECCryptoException::MemoryError,
446                     "NSS:RSA Error attempting to clone (copy) exponent");
447         }
448     }
449 
450     return ret;
451 }
452 
453 // --------------------------------------------------------------------------------
454 //           decrypt a buffer
455 // --------------------------------------------------------------------------------
456 
privateDecrypt(const unsigned char * inBuf,unsigned char * plainBuf,unsigned int inLength,unsigned int maxOutLength,PaddingType padding,const XMLCh * hashURI,const XMLCh * mgfURI,unsigned char * params,unsigned int paramslen) const457 unsigned int NSSCryptoKeyRSA::privateDecrypt(const unsigned char * inBuf,
458                                  unsigned char * plainBuf,
459                                  unsigned int inLength,
460                                  unsigned int maxOutLength,
461                                  PaddingType padding,
462                                  const XMLCh* hashURI,
463                                  const XMLCh* mgfURI,
464                                  unsigned char* params,
465                                  unsigned int paramslen) const {
466 
467     // Perform a decrypt
468     if (mp_privkey == 0) {
469         throw XSECCryptoException(XSECCryptoException::RSAError,
470             "NSS:RSA - Attempt to decrypt data with empty key");
471     }
472 
473     unsigned int decryptSize = inLength;
474 
475     SECStatus s;
476     unsigned char *ptr = NULL;
477 
478     switch (padding) {
479 
480     case XSECCryptoKeyRSA::PAD_PKCS_1_5 :
481 
482     s = PK11_PubDecryptRaw(mp_privkey,
483                            plainBuf,
484                            (unsigned int*)&decryptSize,
485                            maxOutLength,
486                            (unsigned char*)inBuf,
487                            inLength);
488 
489     if (s != SECSuccess) {
490 
491             throw XSECCryptoException(XSECCryptoException::RSAError,
492                 "NSS:RSA privateKeyDecrypt - Error Decrypting PKCS1_5 padded RSA encrypt");
493 
494         }
495 
496         //do the padding (http://www.w3.org/TR/xmlenc-core/#rsa-1_5)
497         ptr = (unsigned char*) memchr(plainBuf, 0x02, decryptSize);
498         if( ptr )
499         {
500             unsigned int bytesToRemove = ((ptr-plainBuf)+1);
501             memmove(plainBuf, ptr+1, decryptSize-bytesToRemove);
502             decryptSize -= bytesToRemove;
503         }
504 
505         ptr = (unsigned char*) memchr(plainBuf, 0x00, decryptSize);
506         if( ptr )
507         {
508             unsigned int bytesToRemove = ((ptr-plainBuf)+1);
509             memmove(plainBuf, ptr+1, decryptSize-bytesToRemove);
510             decryptSize -= bytesToRemove;
511         }
512 
513         break;
514 
515     case XSECCryptoKeyRSA::PAD_OAEP :
516         throw XSECCryptoException(XSECCryptoException::RSAError,
517             "NSS:RSA - OAEP padding method not supported in NSS yet");
518         break;
519 
520 
521     default :
522         throw XSECCryptoException(XSECCryptoException::RSAError,
523             "NSS:RSA - Unknown padding method");
524     }
525 
526     return decryptSize;
527 }
528 
529 // --------------------------------------------------------------------------------
530 //           Encrypt a buffer
531 // --------------------------------------------------------------------------------
532 
publicEncrypt(const unsigned char * inBuf,unsigned char * cipherBuf,unsigned int inLength,unsigned int maxOutLength,PaddingType padding,const XMLCh * hashURI,const XMLCh * mgfURI,unsigned char * params,unsigned int paramslen) const533 unsigned int NSSCryptoKeyRSA::publicEncrypt(const unsigned char * inBuf,
534                                  unsigned char * cipherBuf,
535                                  unsigned int inLength,
536                                  unsigned int maxOutLength,
537                                  PaddingType padding,
538                                  const XMLCh* hashURI,
539                                  const XMLCh* mgfURI,
540                                  unsigned char* params,
541                                  unsigned int paramslen) const {
542 
543     // Perform an encrypt
544     if (mp_pubkey == 0) {
545         throw XSECCryptoException(XSECCryptoException::RSAError,
546             "NSS:RSA - Attempt to encrypt data with empty key");
547     }
548 
549     unsigned int encryptSize = SECKEY_PublicKeyStrength(mp_pubkey);
550 
551     if (maxOutLength < encryptSize) {
552         throw XSECCryptoException(XSECCryptoException::RSAError,
553             "NSS:RSA - Too small buffer for encrypted buffer output");
554     }
555 
556     SECStatus s;
557 
558     unsigned char * buf;
559     XSECnew(buf, unsigned char[encryptSize]);
560     ArrayJanitor<unsigned char> j_buf(buf);
561 
562     switch (padding) {
563     case XSECCryptoKeyRSA::PAD_PKCS_1_5 :
564 
565     // do the padding (http://www.w3.org/TR/xmlenc-core/#rsa-1_5)
566     {
567 
568       // generate random data for padding
569       SECStatus s = PK11_GenerateRandom(buf, encryptSize);
570 
571       if (s != SECSuccess) {
572           throw XSECException(XSECException::InternalError,
573                 "NSSCryptoKeyRSA() - Error generating Random data");
574       }
575 
576       // first byte have to be 0x02
577       buf[0] = 0x00;
578       buf[1] = 0x02;
579 
580       // check that there are no 0x00 bytes among random data
581       for (unsigned int i = 2; i < encryptSize - inLength - 1; i++) {
582 
583           while (buf[i] == 0x00) {
584               // replace all 0x00 occurences in random data with random value
585               PK11_GenerateRandom(&buf[i], 1);
586           }
587       }
588 
589       // before key add 0x00 byte
590       buf[encryptSize - inLength - 1] = 0x00;
591 
592       // at the end of input buffer (to be encrypted) add key
593       memcpy(&buf[encryptSize - inLength], inBuf, inLength);
594     }
595 
596     // encrypt
597     s = PK11_PubEncryptRaw(mp_pubkey, cipherBuf, (unsigned char*)buf, encryptSize, NULL);
598 
599     if (s != SECSuccess) {
600             throw XSECCryptoException(XSECCryptoException::RSAError,
601                 "NSS:RSA publicKeyEncrypt - Error performing encrypt");
602     }
603 
604       break;
605 
606     case XSECCryptoKeyRSA::PAD_OAEP :
607         throw XSECCryptoException(XSECCryptoException::RSAError,
608             "NSS:RSA - OAEP padding method not supported in NSS yet");
609         break;
610 
611     default :
612         throw XSECCryptoException(XSECCryptoException::RSAError,
613             "NSS:RSA - Unknown padding method");
614     }
615 
616     return encryptSize;
617 }
618 
619 // --------------------------------------------------------------------------------
620 //           Get key size in bytes
621 // --------------------------------------------------------------------------------
622 
getLength(void) const623 unsigned int NSSCryptoKeyRSA::getLength(void)  const {
624 
625     unsigned int ret = 0;
626 
627       if (mp_pubkey != 0) {
628           ret = SECKEY_PublicKeyStrength(mp_pubkey);
629       } else if (mp_privkey != 0) {
630           ret = PK11_GetPrivateModulusLen(mp_privkey);
631       }
632 
633       return ret;
634 }
635 
636 // --------------------------------------------------------------------------------
637 //           Load parameters from key (utility function)
638 // --------------------------------------------------------------------------------
639 
loadParamsFromKey(void)640 void NSSCryptoKeyRSA::loadParamsFromKey(void) {
641 
642     if (mp_pubkey == 0)
643         return;
644 
645     mp_modulus = SECITEM_DupItem(&(mp_pubkey->u.rsa.modulus));
646 
647     if (mp_modulus == 0) {
648         throw XSECCryptoException(XSECCryptoException::RSAError,
649             "NSS:RSA - Error during extracting modulus from public key");
650     }
651 
652     mp_exponent = SECITEM_DupItem(&(mp_pubkey->u.rsa.publicExponent));
653 
654     if (mp_exponent == 0) {
655         throw XSECCryptoException(XSECCryptoException::RSAError,
656             "NSS:RSA - Error during extracting exponent from public key");
657     }
658 }
659 
660 // --------------------------------------------------------------------------------
661 //           Get exponent
662 // --------------------------------------------------------------------------------
663 
getExponentBase64BigNums(char * b64,unsigned int len)664 unsigned int NSSCryptoKeyRSA::getExponentBase64BigNums(char * b64, unsigned int len) {
665 
666     if (mp_pubkey == 0 && mp_exponent == 0) {
667         return 0;    // Nothing we can do
668     }
669 
670     if (mp_exponent == NULL) {
671         loadParamsFromKey();
672     }
673 
674     unsigned int bLen = 0;
675     unsigned char * b =  NSSCryptoProvider::SI2b64(mp_exponent, bLen);
676     if (bLen > len)
677         bLen = len;
678     memcpy(b64, b, bLen);
679     delete[] b;
680 
681     return bLen;
682 }
683 
684 // --------------------------------------------------------------------------------
685 //           Get modulus
686 // --------------------------------------------------------------------------------
687 
getModulusBase64BigNums(char * b64,unsigned int len)688 unsigned int NSSCryptoKeyRSA::getModulusBase64BigNums(char * b64, unsigned int len) {
689 
690     if (mp_pubkey == 0 && mp_modulus == 0) {
691         return 0;    // Nothing we can do
692     }
693 
694     if (mp_modulus == NULL) {
695         loadParamsFromKey();
696     }
697 
698     unsigned int bLen = 0;
699     unsigned char * b =  NSSCryptoProvider::SI2b64(mp_modulus, bLen);
700     if (bLen > len)
701         bLen = len;
702     memcpy(b64, b, bLen);
703     delete[] b;
704 
705     return bLen;
706 }
707 
708 #endif /* XSEC_HAVE_NSS */
709