Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of CyaSSL by
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
Generated on Sat Jul 16 2022 04:51:03 by
1.7.2
