sara matheu / CyaSSL

Fork of CyaSSL by Todd Ouska

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers rsa.c Source File

rsa.c

00001 /* rsa.c
00002  *
00003  * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
00004  *
00005  * This file is part of CyaSSL.
00006  *
00007  * CyaSSL is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * CyaSSL is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
00020  */
00021 
00022 
00023 
00024 #include "ctc_rsa.h"
00025 #include "random.h"
00026 #include "error.h"
00027 
00028 #ifdef SHOW_GEN
00029     #include <stdio.h>
00030 #endif
00031 
00032 
00033 enum {
00034     RSA_PUBLIC_ENCRYPT  = 0,
00035     RSA_PUBLIC_DECRYPT  = 1,
00036     RSA_PRIVATE_ENCRYPT = 2,
00037     RSA_PRIVATE_DECRYPT = 3,
00038 
00039     RSA_BLOCK_TYPE_1 = 1,
00040     RSA_BLOCK_TYPE_2 = 2,
00041 
00042     RSA_MIN_SIZE = 512,
00043     RSA_MAX_SIZE = 4096,
00044 
00045     RSA_MIN_PAD_SZ   = 11      /* seperator + 0 + pad value + 8 pads */
00046 };
00047 
00048 int MakeRsaKey(RsaKey* key, int size, long e, RNG* rng)
00049 {
00050     mp_int p, q, tmp1, tmp2, tmp3;
00051     int    err;
00052 
00053     if (key == NULL || rng == NULL)
00054         return -1;
00055 
00056     if (size < RSA_MIN_SIZE || size > RSA_MAX_SIZE)
00057         return -1;
00058 
00059     if (e < 3 || (e & 1) == 0)
00060         return -1;
00061 
00062     if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != MP_OKAY)
00063         return err;
00064 
00065     err = mp_set_int(&tmp3, e);
00066 
00067     /* make p */
00068     if (err == MP_OKAY) {
00069         do {
00070             err = rand_prime(&p, size/16, rng, key->heap); /* size in bytes/2 */
00071 
00072             if (err == MP_OKAY)
00073                 err = mp_sub_d(&p, 1, &tmp1);  /* tmp1 = p-1 */
00074 
00075             if (err == MP_OKAY)
00076                 err = mp_gcd(&tmp1, &tmp3, &tmp2);  /* tmp2 = gcd(p-1, e) */
00077         } while (err == MP_OKAY && mp_cmp_d(&tmp2, 1) != 0);  /* e divdes p-1 */
00078     }
00079 
00080     /* make q */
00081     if (err == MP_OKAY) {
00082         do {
00083             err = rand_prime(&q, size/16, rng, key->heap); /* size in bytes/2 */
00084 
00085             if (err == MP_OKAY)
00086                 err = mp_sub_d(&q, 1, &tmp1);  /* tmp1 = q-1 */
00087 
00088             if (err == MP_OKAY)
00089                 err = mp_gcd(&tmp1, &tmp3, &tmp2);  /* tmp2 = gcd(q-1, e) */
00090         } while (err == MP_OKAY && mp_cmp_d(&tmp2, 1) != 0);  /* e divdes q-1 */
00091     }
00092 
00093     if (err == MP_OKAY)
00094         err = mp_init_multi(&key->n, &key->e, &key->d, &key->p, &key->q, NULL);
00095 
00096     if (err == MP_OKAY)
00097         err = mp_init_multi(&key->dP, &key->dP, &key->u, NULL, NULL, NULL);
00098 
00099     if (err == MP_OKAY)
00100         err = mp_sub_d(&p, 1, &tmp2);  /* tmp2 = p-1 */
00101 
00102     if (err == MP_OKAY)
00103         err = mp_lcm(&tmp1, &tmp2, &tmp1);  /* tmp1 = lcm(p-1, q-1),last loop */
00104 
00105     /* make key */
00106     if (err == MP_OKAY)
00107         err = mp_set_int(&key->e, e);  /* key->e = e */
00108 
00109     if (err == MP_OKAY)                /* key->d = 1/e mod lcm(p-1, q-1) */
00110         err = mp_invmod(&key->e, &tmp1, &key->d);
00111 
00112     if (err == MP_OKAY)
00113         err = mp_mul(&p, &q, &key->n);  /* key->n = pq */
00114 
00115     if (err == MP_OKAY)
00116         err = mp_sub_d(&p, 1, &tmp1);
00117 
00118     if (err == MP_OKAY)
00119         err = mp_sub_d(&q, 1, &tmp2);
00120 
00121     if (err == MP_OKAY)
00122         err = mp_mod(&key->d, &tmp1, &key->dP);
00123 
00124     if (err == MP_OKAY)
00125         err = mp_mod(&key->d, &tmp2, &key->dQ);
00126 
00127     if (err == MP_OKAY)
00128         err = mp_invmod(&q, &p, &key->u);
00129 
00130     if (err == MP_OKAY)
00131         err = mp_copy(&p, &key->p);
00132 
00133     if (err == MP_OKAY)
00134         err = mp_copy(&q, &key->q);
00135 
00136     if (err == MP_OKAY)
00137         key->type = RSA_PRIVATE; 
00138 
00139     mp_clear(&tmp3); 
00140     mp_clear(&tmp2); 
00141     mp_clear(&tmp1); 
00142     mp_clear(&q); 
00143     mp_clear(&p);
00144 
00145     if (err != MP_OKAY) {
00146         FreeRsaKey(key);        
00147         return err;
00148     }
00149 
00150     return 0;
00151 }
00152 void InitRsaKey(RsaKey* key, void* heap)
00153 {
00154     key->type = -1;  /* haven't decdied yet */
00155     key->heap = heap;
00156 
00157 /* TomsFastMath doesn't use memory allocation */
00158 #ifndef USE_FAST_MATH
00159     key->n.dp = key->e.dp = 0;  /* public  alloc parts */
00160 
00161     key->d.dp = key->p.dp  = 0;  /* private alloc parts */
00162     key->q.dp = key->dP.dp = 0;  
00163     key->u.dp = key->dQ.dp = 0;
00164 #endif
00165 }
00166 
00167 
00168 void FreeRsaKey(RsaKey* key)
00169 {
00170 /* TomsFastMath doesn't use memory allocation */
00171 #ifndef USE_FAST_MATH
00172     if (key->type == RSA_PRIVATE) {
00173         mp_clear(&key->u);
00174         mp_clear(&key->dQ);
00175         mp_clear(&key->dP);
00176         mp_clear(&key->q);
00177         mp_clear(&key->p);
00178         mp_clear(&key->d);
00179     }
00180     mp_clear(&key->e);
00181     mp_clear(&key->n);
00182 #endif
00183 }
00184 
00185 static void RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock,
00186                    word32 pkcsBlockLen, byte padValue, RNG* rng)
00187 {
00188     if (inputLen == 0) return;
00189 
00190     pkcsBlock[0] = 0x0;       /* set first byte to zero and advance */
00191     pkcsBlock++; pkcsBlockLen--;
00192     pkcsBlock[0] = padValue;  /* insert padValue */
00193 
00194     if (padValue == RSA_BLOCK_TYPE_1)
00195         /* pad with 0xff bytes */
00196         XMEMSET(&pkcsBlock[1], 0xFF, pkcsBlockLen - inputLen - 2);
00197     else {
00198         /* pad with non-zero random bytes */
00199         word32 padLen = pkcsBlockLen - inputLen - 1, i;
00200         RNG_GenerateBlock(rng, &pkcsBlock[1], padLen);
00201 
00202         /* remove zeros */
00203         for (i = 1; i < padLen; i++)
00204             if (pkcsBlock[i] == 0) pkcsBlock[i] = 0x01;
00205     }
00206 
00207     pkcsBlock[pkcsBlockLen-inputLen-1] = 0;     /* separator */
00208     XMEMCPY(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen);
00209 }
00210 
00211 
00212 static word32 RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen,
00213                        byte **output, byte padValue)
00214 {
00215     word32 maxOutputLen = (pkcsBlockLen > 10) ? (pkcsBlockLen - 10) : 0,
00216            invalid = 0,
00217            i = 1,
00218            outputLen;
00219 
00220     if (pkcsBlock[0] != 0x0) /* skip past zero */
00221         invalid = 1;
00222     pkcsBlock++; pkcsBlockLen--;
00223 
00224     /* Require block type padValue */
00225     invalid = (pkcsBlock[0] != padValue) || invalid;
00226 
00227     /* skip past the padding until we find the separator */
00228     while (i<pkcsBlockLen && pkcsBlock[i++]) { /* null body */
00229         }
00230     if(!(i==pkcsBlockLen || pkcsBlock[i-1]==0))
00231         return 0;
00232 
00233     outputLen = pkcsBlockLen - i;
00234     invalid = (outputLen > maxOutputLen) || invalid;
00235 
00236     if (invalid)
00237         return 0;
00238 
00239     *output = (byte *)(pkcsBlock + i);
00240     return outputLen;
00241 }
00242 
00243 
00244 static int RsaFunction(const byte* in, word32 inLen, byte* out, word32* outLen,
00245                        int type, RsaKey* key)
00246 {
00247     #define ERROR_OUT(x) { ret = x; goto done;}
00248 
00249     mp_int tmp;
00250     int    ret = 0;
00251     word32 keyLen, len;
00252 
00253     if (mp_init(&tmp) != MP_OKAY)
00254         return MP_INIT_E;
00255 
00256     if (mp_read_unsigned_bin(&tmp, (byte*)in, inLen) != MP_OKAY)
00257         ERROR_OUT(MP_READ_E);
00258 
00259     if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) {
00260         #ifdef RSA_LOW_MEM      /* half as much memory but twice as slow */
00261             if (mp_exptmod(&tmp, &key->d, &key->n, &tmp) != MP_OKAY)
00262                 ERROR_OUT(MP_EXPTMOD_E);
00263         #else
00264             #define INNER_ERROR_OUT(x) { ret = x; goto inner_done; }
00265 
00266             mp_int tmpa, tmpb;
00267 
00268             if (mp_init(&tmpa) != MP_OKAY)
00269                 ERROR_OUT(MP_INIT_E);
00270 
00271             if (mp_init(&tmpb) != MP_OKAY) {
00272                 mp_clear(&tmpa);
00273                 ERROR_OUT(MP_INIT_E);
00274             }
00275 
00276             /* tmpa = tmp^dP mod p */
00277             if (mp_exptmod(&tmp, &key->dP, &key->p, &tmpa) != MP_OKAY)
00278                 INNER_ERROR_OUT(MP_EXPTMOD_E);
00279 
00280             /* tmpb = tmp^dQ mod q */
00281             if (mp_exptmod(&tmp, &key->dQ, &key->q, &tmpb) != MP_OKAY)
00282                 INNER_ERROR_OUT(MP_EXPTMOD_E);
00283 
00284             /* tmp = (tmpa - tmpb) * qInv (mod p) */
00285             if (mp_sub(&tmpa, &tmpb, &tmp) != MP_OKAY)
00286                 INNER_ERROR_OUT(MP_SUB_E);
00287 
00288             if (mp_mulmod(&tmp, &key->u, &key->p, &tmp) != MP_OKAY)
00289                 INNER_ERROR_OUT(MP_MULMOD_E);
00290 
00291             /* tmp = tmpb + q * tmp */
00292             if (mp_mul(&tmp, &key->q, &tmp) != MP_OKAY)
00293                 INNER_ERROR_OUT(MP_MUL_E);
00294 
00295             if (mp_add(&tmp, &tmpb, &tmp) != MP_OKAY)
00296                 INNER_ERROR_OUT(MP_ADD_E);
00297 
00298         inner_done:
00299             mp_clear(&tmpa);
00300             mp_clear(&tmpb);
00301 
00302             if (ret != 0) return ret;
00303 
00304         #endif   /* RSA_LOW_MEM */
00305     }
00306     else if (type == RSA_PUBLIC_ENCRYPT || type == RSA_PUBLIC_DECRYPT) {
00307         if (mp_exptmod(&tmp, &key->e, &key->n, &tmp) != MP_OKAY)
00308             ERROR_OUT(MP_EXPTMOD_E);
00309     }
00310     else
00311         ERROR_OUT(RSA_WRONG_TYPE_E);
00312 
00313     keyLen = mp_unsigned_bin_size(&key->n);
00314     if (keyLen > *outLen)
00315         ERROR_OUT(RSA_BUFFER_E);
00316 
00317     len = mp_unsigned_bin_size(&tmp);
00318 
00319     /* pad front w/ zeros to match key length */
00320     while (len < keyLen) {
00321         *out++ = 0x00;
00322         len++;
00323     }
00324 
00325     *outLen = keyLen;
00326 
00327     /* convert */
00328     if (mp_to_unsigned_bin(&tmp, out) != MP_OKAY)
00329         ERROR_OUT(MP_TO_E);
00330    
00331 done: 
00332     mp_clear(&tmp);
00333     return ret;
00334 }
00335 
00336 
00337 
00338 int RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen,
00339                      RsaKey* key, RNG* rng)
00340 {
00341     int sz = mp_unsigned_bin_size(&key->n), ret;
00342 
00343     if (sz > (int)outLen)
00344         return RSA_BUFFER_E;
00345 
00346     if (inLen > (word32)(sz - RSA_MIN_PAD_SZ))
00347         return RSA_BUFFER_E;
00348 
00349     RsaPad(in, inLen, out, sz, RSA_BLOCK_TYPE_2, rng);
00350 
00351     if ((ret = RsaFunction(out, sz, out, &outLen, RSA_PUBLIC_ENCRYPT, key)) < 0)
00352         sz = ret;
00353 
00354     return sz;
00355 }
00356 
00357 
00358 int RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, RsaKey* key)
00359 {
00360     int plainLen, ret;
00361 
00362     if ((ret = RsaFunction(in, inLen, in, &inLen, RSA_PRIVATE_DECRYPT, key))
00363             < 0) {
00364         return ret;
00365     }
00366  
00367     plainLen = RsaUnPad(in, inLen, out, RSA_BLOCK_TYPE_2);
00368 
00369     return plainLen;
00370 }
00371 
00372 int RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, word32 outLen,
00373                      RsaKey* key)
00374 {
00375     int plainLen, ret;
00376     byte*  tmp;
00377     byte*  pad = 0;
00378 
00379     if ( !(tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA)) )
00380         return MEMORY_E;
00381 
00382     XMEMCPY(tmp, in, inLen);
00383 
00384     if ((ret = plainLen = RsaPrivateDecryptInline(tmp, inLen, &pad, key))
00385             < 0) {
00386         XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
00387         return ret;
00388     }
00389     XMEMCPY(out, pad, plainLen);
00390     XMEMSET(tmp, 0x00, inLen); 
00391 
00392     XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
00393     return plainLen;
00394 }
00395 
00396 
00397 /* for Rsa Verify */
00398 int RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key)
00399 {
00400     int plainLen, ret;
00401 
00402     if ((ret = RsaFunction(in, inLen, in, &inLen, RSA_PUBLIC_DECRYPT, key))
00403             < 0) {
00404         return ret;
00405     }
00406   
00407     plainLen = RsaUnPad(in, inLen, out, RSA_BLOCK_TYPE_1);
00408 
00409     return plainLen;
00410 }
00411 
00412 int RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen,
00413                      RsaKey* key)
00414 {
00415     int plainLen, ret;
00416     byte*  tmp;
00417     byte*  pad = 0;
00418 
00419     if ( !(tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA)) )
00420         return MEMORY_E;
00421 
00422     XMEMCPY(tmp, in, inLen);
00423 
00424     if ((ret = plainLen = RsaSSL_VerifyInline(tmp, inLen, &pad, key))
00425             < 0) {
00426         XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
00427         return ret;
00428     }
00429   
00430     XMEMCPY(out, pad, plainLen);
00431     XMEMSET(tmp, 0x00, inLen); 
00432 
00433     XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
00434     return plainLen;
00435 }
00436 
00437 
00438 /* for Rsa Sign */
00439 int RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen,
00440                       RsaKey* key, RNG* rng)
00441 {
00442     int sz = mp_unsigned_bin_size(&key->n), ret;
00443 
00444     if (sz > (int)outLen)
00445         return RSA_BUFFER_E;
00446 
00447     if (inLen > (word32)(sz - RSA_MIN_PAD_SZ))
00448         return RSA_BUFFER_E;
00449 
00450     RsaPad(in, inLen, out, sz, RSA_BLOCK_TYPE_1, rng);
00451 
00452     if ((ret = RsaFunction(out, sz, out, &outLen, RSA_PRIVATE_ENCRYPT,key)) < 0)
00453         sz = ret;
00454     
00455     return sz;
00456 }
00457 
00458 
00459 int RsaEncryptSize(RsaKey* key)
00460 {
00461     return mp_unsigned_bin_size(&key->n);
00462 }
00463 
00464 
00465 #ifdef CYASSL_KEY_GEN
00466 
00467 static const int USE_BBS = 1;
00468 
00469 static int rand_prime(mp_int* N, int len, RNG* rng, void* heap)
00470 {
00471     int   err, res, type;
00472     byte* buf;
00473 
00474     if (N == NULL || rng == NULL)
00475        return -1; 
00476 
00477     /* get type */
00478     if (len < 0) {
00479         type = USE_BBS;
00480         len = -len;
00481     } else {
00482         type = 0;
00483     }
00484 
00485     /* allow sizes between 2 and 512 bytes for a prime size */
00486     if (len < 2 || len > 512) { 
00487         return -1;
00488     }
00489    
00490     /* allocate buffer to work with */
00491     buf = XCALLOC(1, len, heap);
00492     if (buf == NULL) {
00493         return -1;
00494     }
00495 
00496     do {
00497 #ifdef SHOW_GEN
00498         printf(".");
00499         fflush(stdout);
00500 #endif
00501         /* generate value */
00502         RNG_GenerateBlock(rng, buf, len);
00503 
00504         /* munge bits */
00505         buf[0]     |= 0x80 | 0x40;
00506         buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00);
00507  
00508         /* load value */
00509         if ((err = mp_read_unsigned_bin(N, buf, len)) != MP_OKAY) {
00510             XFREE(buf, heap, DYNAMIC_TYPE_RSA);
00511             return err;
00512         }
00513 
00514         /* test */
00515         if ((err = mp_prime_is_prime(N, 8, &res)) != MP_OKAY) {
00516             XFREE(buf, heap, DYNAMIC_TYPE_RSA);
00517             return err;
00518         }
00519     } while (res == MP_NO);
00520 
00521 #ifdef LTC_CLEAN_STACK
00522     XMEMSET(buf, 0, len);
00523 #endif
00524 
00525     XFREE(buf, heap, DYNAMIC_TYPE_RSA);
00526     return 0;
00527 }
00528 
00529 
00530 /* Make an RSA key for size bits, with e specified, 65537 is a good e */
00531 int MakeRsaKey(RsaKey* key, int size, long e, RNG* rng)
00532 {
00533     mp_int p, q, tmp1, tmp2, tmp3;
00534     int    err;
00535 
00536     if (key == NULL || rng == NULL)
00537         return -1;
00538 
00539     if (size < RSA_MIN_SIZE || size > RSA_MAX_SIZE)
00540         return -1;
00541 
00542     if (e < 3 || (e & 1) == 0)
00543         return -1;
00544 
00545     if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != MP_OKAY)
00546         return err;
00547 
00548     err = mp_set_int(&tmp3, e);
00549 
00550     /* make p */
00551     if (err == MP_OKAY) {
00552         do {
00553             err = rand_prime(&p, size/16, rng, key->heap); /* size in bytes/2 */
00554 
00555             if (err == MP_OKAY)
00556                 err = mp_sub_d(&p, 1, &tmp1);  /* tmp1 = p-1 */
00557 
00558             if (err == MP_OKAY)
00559                 err = mp_gcd(&tmp1, &tmp3, &tmp2);  /* tmp2 = gcd(p-1, e) */
00560         } while (err == MP_OKAY && mp_cmp_d(&tmp2, 1) != 0);  /* e divdes p-1 */
00561     }
00562 
00563     /* make q */
00564     if (err == MP_OKAY) {
00565         do {
00566             err = rand_prime(&q, size/16, rng, key->heap); /* size in bytes/2 */
00567 
00568             if (err == MP_OKAY)
00569                 err = mp_sub_d(&q, 1, &tmp1);  /* tmp1 = q-1 */
00570 
00571             if (err == MP_OKAY)
00572                 err = mp_gcd(&tmp1, &tmp3, &tmp2);  /* tmp2 = gcd(q-1, e) */
00573         } while (err == MP_OKAY && mp_cmp_d(&tmp2, 1) != 0);  /* e divdes q-1 */
00574     }
00575 
00576     if (err == MP_OKAY)
00577         err = mp_init_multi(&key->n, &key->e, &key->d, &key->p, &key->q, NULL);
00578 
00579     if (err == MP_OKAY)
00580         err = mp_init_multi(&key->dP, &key->dP, &key->u, NULL, NULL, NULL);
00581 
00582     if (err == MP_OKAY)
00583         err = mp_sub_d(&p, 1, &tmp2);  /* tmp2 = p-1 */
00584 
00585     if (err == MP_OKAY)
00586         err = mp_lcm(&tmp1, &tmp2, &tmp1);  /* tmp1 = lcm(p-1, q-1),last loop */
00587 
00588     /* make key */
00589     if (err == MP_OKAY)
00590         err = mp_set_int(&key->e, e);  /* key->e = e */
00591 
00592     if (err == MP_OKAY)                /* key->d = 1/e mod lcm(p-1, q-1) */
00593         err = mp_invmod(&key->e, &tmp1, &key->d);
00594 
00595     if (err == MP_OKAY)
00596         err = mp_mul(&p, &q, &key->n);  /* key->n = pq */
00597 
00598     if (err == MP_OKAY)
00599         err = mp_sub_d(&p, 1, &tmp1);
00600 
00601     if (err == MP_OKAY)
00602         err = mp_sub_d(&q, 1, &tmp2);
00603 
00604     if (err == MP_OKAY)
00605         err = mp_mod(&key->d, &tmp1, &key->dP);
00606 
00607     if (err == MP_OKAY)
00608         err = mp_mod(&key->d, &tmp2, &key->dQ);
00609 
00610     if (err == MP_OKAY)
00611         err = mp_invmod(&q, &p, &key->u);
00612 
00613     if (err == MP_OKAY)
00614         err = mp_copy(&p, &key->p);
00615 
00616     if (err == MP_OKAY)
00617         err = mp_copy(&q, &key->q);
00618 
00619     if (err == MP_OKAY)
00620         key->type = RSA_PRIVATE; 
00621 
00622     mp_clear(&tmp3); 
00623     mp_clear(&tmp2); 
00624     mp_clear(&tmp1); 
00625     mp_clear(&q); 
00626     mp_clear(&p);
00627 
00628     if (err != MP_OKAY) {
00629         FreeRsaKey(key);        
00630         return err;
00631     }
00632 
00633     return 0;
00634 }
00635 
00636 
00637 #endif /* CYASLS_KEY_GEN */
00638