Back to index

lightning-sunbird  0.9+nobinonly
keystuff.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include <stdio.h>
00039 #include <string.h>
00040 #include "secutil.h"
00041 
00042 #if defined(XP_UNIX)
00043 #include <unistd.h>
00044 #include <sys/time.h>
00045 #include <termios.h>
00046 #endif
00047 
00048 #if defined(XP_WIN) || defined (XP_PC)
00049 #include <time.h>
00050 #include <conio.h>
00051 #endif
00052 
00053 #if defined(__sun) && !defined(SVR4)
00054 extern int fclose(FILE*);
00055 extern int fprintf(FILE *, char *, ...);
00056 extern int isatty(int);
00057 extern char *sys_errlist[];
00058 #define strerror(errno) sys_errlist[errno]
00059 #endif
00060 
00061 #include "nspr.h"
00062 #include "prtypes.h"
00063 #include "prtime.h"
00064 #include "prlong.h"
00065 
00066 #include "pk11func.h"
00067 
00068 #define NUM_KEYSTROKES 120
00069 #define RAND_BUF_SIZE 60
00070 
00071 #define ERROR_BREAK rv = SECFailure;break;
00072 
00073 const SEC_ASN1Template SECKEY_PQGParamsTemplate[] = {
00074     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPQGParams) },
00075     { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,prime) },
00076     { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,subPrime) },
00077     { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,base) },
00078     { 0, }
00079 };
00080 
00081 /* returns 0 for success, -1 for failure (EOF encountered) */
00082 static int
00083 UpdateRNG(void)
00084 {
00085     char *         randbuf;
00086     int            fd, i, count;
00087     int            c;
00088     int            rv              = 0;
00089 #ifdef XP_UNIX
00090     cc_t           orig_cc_min;
00091     cc_t           orig_cc_time;
00092     tcflag_t       orig_lflag;
00093     struct termios tio;
00094 #endif
00095 
00096 #define FPS fprintf(stderr, 
00097     FPS "\n");
00098     FPS "A random seed must be generated that will be used in the\n");
00099     FPS "creation of your key.  One of the easiest ways to create a\n");
00100     FPS "random seed is to use the timing of keystrokes on a keyboard.\n");
00101     FPS "\n");
00102     FPS "To begin, type keys on the keyboard until this progress meter\n");
00103     FPS "is full.  DO NOT USE THE AUTOREPEAT FUNCTION ON YOUR KEYBOARD!\n");
00104     FPS "\n");
00105     FPS "\n");
00106     FPS "Continue typing until the progress meter is full:\n\n");
00107     FPS "|                                                            |\r");
00108 
00109     /* turn off echo on stdin & return on 1 char instead of NL */
00110     fd = fileno(stdin);
00111 
00112 #if defined(XP_UNIX) && !defined(VMS)
00113     tcgetattr(fd, &tio);
00114     orig_lflag = tio.c_lflag;
00115     orig_cc_min = tio.c_cc[VMIN];
00116     orig_cc_time = tio.c_cc[VTIME];
00117     tio.c_lflag &= ~ECHO;
00118     tio.c_lflag &= ~ICANON;
00119     tio.c_cc[VMIN] = 1;
00120     tio.c_cc[VTIME] = 0;
00121     tcsetattr(fd, TCSAFLUSH, &tio);
00122 #endif
00123 
00124     /* Get random noise from keyboard strokes */
00125     randbuf = (char *) PORT_Alloc(RAND_BUF_SIZE);
00126     count = 0;
00127     while (count < NUM_KEYSTROKES+1) {
00128 #ifdef VMS
00129        c = GENERIC_GETCHAR_NOECHO();
00130 #elif XP_UNIX
00131        c = getc(stdin);
00132 #else
00133        c = getch();
00134 #endif
00135        if (c == EOF) {
00136            rv = -1;
00137            break;
00138        }
00139        PK11_RandomUpdate(randbuf, sizeof(randbuf));
00140        if (c != randbuf[0]) {
00141            randbuf[0] = c;
00142            FPS "\r|");
00143            for (i=0; i<count/(NUM_KEYSTROKES/RAND_BUF_SIZE); i++) {
00144               FPS "*");
00145            }
00146            if (count%(NUM_KEYSTROKES/RAND_BUF_SIZE) == 1)
00147               FPS "/");
00148            count++;
00149        }
00150     }
00151     free(randbuf); 
00152 
00153     FPS "\n\n");
00154     FPS "Finished.  Press enter to continue: ");
00155 #if defined(VMS)
00156     while((c = GENERIC_GETCHAR_NO_ECHO()) != '\r' && c != EOF)
00157        ;
00158 #else
00159     while ((c = getc(stdin)) != '\n' && c != EOF)
00160        ;
00161 #endif
00162     if (c == EOF) 
00163        rv = -1;
00164     FPS "\n");
00165 
00166 #undef FPS
00167 
00168 #if defined(XP_UNIX) && !defined(VMS)
00169     /* set back termio the way it was */
00170     tio.c_lflag = orig_lflag;
00171     tio.c_cc[VMIN] = orig_cc_min;
00172     tio.c_cc[VTIME] = orig_cc_time;
00173     tcsetattr(fd, TCSAFLUSH, &tio);
00174 #endif
00175     return rv;
00176 }
00177 
00178 
00179 static const unsigned char P[] = 
00180                            { 0x00, 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76,
00181                           0xaa, 0x3d, 0x25, 0x75, 0x9b, 0xb0, 0x68, 0x69,
00182                           0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, 0x0c,
00183                           0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82,
00184                           0xe5, 0xd0, 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e,
00185                           0xaf, 0xc2, 0xe9, 0xad, 0xac, 0x32, 0xab, 0x7a,
00186                           0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24,
00187                           0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02,
00188                           0x91 };
00189 static const unsigned char Q[] = 
00190                            { 0x00, 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8,
00191                           0xee, 0x99, 0x3b, 0x4f, 0x2d, 0xed, 0x30, 0xf4,
00192                           0x8e, 0xda, 0xce, 0x91, 0x5f };
00193 static const unsigned char G[] = 
00194                            { 0x00, 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a,
00195                           0x13, 0x41, 0x31, 0x63, 0xa5, 0x5b, 0x4c, 0xb5,
00196                           0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, 0xef,
00197                           0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c,
00198                           0x2e, 0x71, 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba,
00199                           0xbf, 0x58, 0xe5, 0xb7, 0x95, 0x21, 0x92, 0x5c,
00200                           0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08,
00201                           0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88,
00202                           0x02 };
00203 
00204 static const SECKEYPQGParams default_pqg_params = {
00205     NULL,
00206     { 0, (unsigned char *)P, sizeof(P) },
00207     { 0, (unsigned char *)Q, sizeof(Q) },
00208     { 0, (unsigned char *)G, sizeof(G) }
00209 };
00210 
00211 static SECKEYPQGParams *
00212 decode_pqg_params(const char *str)
00213 {
00214     char *buf;
00215     unsigned int len;
00216     PRArenaPool *arena;
00217     SECKEYPQGParams *params;
00218     SECStatus status;
00219  
00220     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
00221     if (arena == NULL)
00222         return NULL;
00223  
00224     params = PORT_ArenaZAlloc(arena, sizeof(SECKEYPQGParams));
00225     if (params == NULL)
00226         goto loser;
00227     params->arena = arena;
00228  
00229     buf = (char *)ATOB_AsciiToData(str, &len);
00230     if ((buf == NULL) || (len == 0))
00231         goto loser;
00232  
00233     status = SEC_ASN1Decode(arena, params, SECKEY_PQGParamsTemplate, buf, len);
00234     if (status != SECSuccess)
00235         goto loser;
00236  
00237     return params;
00238  
00239 loser:
00240     if (arena != NULL)
00241         PORT_FreeArena(arena, PR_FALSE);
00242     return NULL;
00243 }
00244 
00245 void  
00246 CERTUTIL_DestroyParamsPQG(SECKEYPQGParams *params)
00247 {
00248     if (params->arena) {
00249         PORT_FreeArena(params->arena, PR_FALSE);
00250     }
00251 }
00252 
00253 static int
00254 pqg_prime_bits(const SECKEYPQGParams *params)
00255 {
00256     int primeBits = 0;
00257  
00258     if (params != NULL) {
00259        int i;
00260        for (i = 0; params->prime.data[i] == 0; i++) {
00261            /* empty */;
00262        }
00263        primeBits = (params->prime.len - i) * 8;
00264     }
00265  
00266     return primeBits;
00267 }
00268 
00269 static char *
00270 getPQGString(const char *filename)
00271 {
00272     unsigned char *buf      = NULL;
00273     PRFileDesc    *src;
00274     PRInt32        numBytes;
00275     PRStatus       prStatus;
00276     PRFileInfo     info;
00277 
00278     src   = PR_Open(filename, PR_RDONLY, 0);
00279     if (!src) {
00280        fprintf(stderr, "Failed to open PQG file %s\n", filename);
00281        return NULL;
00282     }
00283 
00284     prStatus = PR_GetOpenFileInfo(src, &info);
00285 
00286     if (prStatus == PR_SUCCESS) {
00287        buf = (unsigned char*)PORT_Alloc(info.size + 1);
00288     }
00289     if (!buf) {
00290        PR_Close(src);
00291        fprintf(stderr, "Failed to read PQG file %s\n", filename);
00292        return NULL;
00293     }
00294 
00295     numBytes = PR_Read(src, buf, info.size);
00296     PR_Close(src);
00297     if (numBytes != info.size) {
00298        PORT_Free(buf);
00299        fprintf(stderr, "Failed to read PQG file %s\n", filename);
00300        PORT_SetError(SEC_ERROR_IO);
00301        return NULL;
00302     }
00303 
00304     if (buf[numBytes-1] == '\n') 
00305        numBytes--;
00306     if (buf[numBytes-1] == '\r') 
00307        numBytes--;
00308     buf[numBytes] = 0;
00309     
00310     return (char *)buf;
00311 }
00312 
00313 static SECKEYPQGParams*
00314 getpqgfromfile(int keyBits, const char *pqgFile)
00315 {
00316     char *end, *str, *pqgString;
00317     SECKEYPQGParams* params = NULL;
00318 
00319     str = pqgString = getPQGString(pqgFile);
00320     if (!str) 
00321        return NULL;
00322 
00323     do {
00324        end = PORT_Strchr(str, ',');
00325        if (end)
00326            *end = '\0';
00327        params = decode_pqg_params(str);
00328        if (params) {
00329            int primeBits = pqg_prime_bits(params);
00330            if (keyBits == primeBits)
00331               break;
00332            CERTUTIL_DestroyParamsPQG(params);
00333            params = NULL;
00334        }
00335        if (end)
00336            str = end + 1;
00337     } while (end);
00338 
00339     PORT_Free(pqgString);
00340     return params;
00341 }
00342 
00343 static SECStatus 
00344 CERTUTIL_FileForRNG(const char *noise)
00345 {
00346     char buf[2048];
00347     PRFileDesc *fd;
00348     PRInt32 count;
00349 
00350     fd = PR_Open(noise,PR_RDONLY,0);
00351     if (!fd) {
00352        fprintf(stderr, "failed to open noise file.");
00353        return SECFailure;
00354     }
00355 
00356     do {
00357        count = PR_Read(fd,buf,sizeof(buf));
00358        if (count > 0) {
00359            PK11_RandomUpdate(buf,count);
00360        }
00361     } while (count > 0);
00362 
00363     PR_Close(fd);
00364     return SECSuccess;
00365 }
00366 
00367 #ifdef NSS_ENABLE_ECC
00368 typedef struct curveNameTagPairStr {
00369     char *curveName;
00370     SECOidTag curveOidTag;
00371 } CurveNameTagPair;
00372 
00373 #define DEFAULT_CURVE_OID_TAG  SEC_OID_SECG_EC_SECP192R1
00374 /* #define DEFAULT_CURVE_OID_TAG  SEC_OID_SECG_EC_SECP160R1 */
00375 
00376 static CurveNameTagPair nameTagPair[] =
00377 { 
00378   { "sect163k1", SEC_OID_SECG_EC_SECT163K1},
00379   { "nistk163", SEC_OID_SECG_EC_SECT163K1},
00380   { "sect163r1", SEC_OID_SECG_EC_SECT163R1},
00381   { "sect163r2", SEC_OID_SECG_EC_SECT163R2},
00382   { "nistb163", SEC_OID_SECG_EC_SECT163R2},
00383   { "sect193r1", SEC_OID_SECG_EC_SECT193R1},
00384   { "sect193r2", SEC_OID_SECG_EC_SECT193R2},
00385   { "sect233k1", SEC_OID_SECG_EC_SECT233K1},
00386   { "nistk233", SEC_OID_SECG_EC_SECT233K1},
00387   { "sect233r1", SEC_OID_SECG_EC_SECT233R1},
00388   { "nistb233", SEC_OID_SECG_EC_SECT233R1},
00389   { "sect239k1", SEC_OID_SECG_EC_SECT239K1},
00390   { "sect283k1", SEC_OID_SECG_EC_SECT283K1},
00391   { "nistk283", SEC_OID_SECG_EC_SECT283K1},
00392   { "sect283r1", SEC_OID_SECG_EC_SECT283R1},
00393   { "nistb283", SEC_OID_SECG_EC_SECT283R1},
00394   { "sect409k1", SEC_OID_SECG_EC_SECT409K1},
00395   { "nistk409", SEC_OID_SECG_EC_SECT409K1},
00396   { "sect409r1", SEC_OID_SECG_EC_SECT409R1},
00397   { "nistb409", SEC_OID_SECG_EC_SECT409R1},
00398   { "sect571k1", SEC_OID_SECG_EC_SECT571K1},
00399   { "nistk571", SEC_OID_SECG_EC_SECT571K1},
00400   { "sect571r1", SEC_OID_SECG_EC_SECT571R1},
00401   { "nistb571", SEC_OID_SECG_EC_SECT571R1},
00402   { "secp160k1", SEC_OID_SECG_EC_SECP160K1},
00403   { "secp160r1", SEC_OID_SECG_EC_SECP160R1},
00404   { "secp160r2", SEC_OID_SECG_EC_SECP160R2},
00405   { "secp192k1", SEC_OID_SECG_EC_SECP192K1},
00406   { "secp192r1", SEC_OID_SECG_EC_SECP192R1},
00407   { "nistp192", SEC_OID_SECG_EC_SECP192R1},
00408   { "secp224k1", SEC_OID_SECG_EC_SECP224K1},
00409   { "secp224r1", SEC_OID_SECG_EC_SECP224R1},
00410   { "nistp224", SEC_OID_SECG_EC_SECP224R1},
00411   { "secp256k1", SEC_OID_SECG_EC_SECP256K1},
00412   { "secp256r1", SEC_OID_SECG_EC_SECP256R1},
00413   { "nistp256", SEC_OID_SECG_EC_SECP256R1},
00414   { "secp384r1", SEC_OID_SECG_EC_SECP384R1},
00415   { "nistp384", SEC_OID_SECG_EC_SECP384R1},
00416   { "secp521r1", SEC_OID_SECG_EC_SECP521R1},
00417   { "nistp521", SEC_OID_SECG_EC_SECP521R1},
00418 
00419   { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 },
00420   { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 },
00421   { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 },
00422   { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 },
00423   { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 },
00424   { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 },
00425 
00426   { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 },
00427   { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 },
00428   { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 },
00429   { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 },
00430   { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 },
00431   { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 },
00432   { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 },
00433   { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 },
00434   { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 },
00435   { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 },
00436   { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 },
00437   { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 },
00438   { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 },
00439   { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 },
00440   { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 },
00441   { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 },
00442   { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 },
00443   { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 },
00444   { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 },
00445   { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 },
00446 
00447   { "secp112r1", SEC_OID_SECG_EC_SECP112R1},
00448   { "secp112r2", SEC_OID_SECG_EC_SECP112R2},
00449   { "secp128r1", SEC_OID_SECG_EC_SECP128R1},
00450   { "secp128r2", SEC_OID_SECG_EC_SECP128R2},
00451 
00452   { "sect113r1", SEC_OID_SECG_EC_SECT113R1},
00453   { "sect113r2", SEC_OID_SECG_EC_SECT113R2},
00454   { "sect131r1", SEC_OID_SECG_EC_SECT131R1},
00455   { "sect131r2", SEC_OID_SECG_EC_SECT131R2},
00456 };
00457 
00458 static SECKEYECParams * 
00459 getECParams(const char *curve)
00460 {
00461     SECKEYECParams *ecparams;
00462     SECOidData *oidData = NULL;
00463     SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */
00464     int i, numCurves;
00465 
00466     if (curve != NULL) {
00467         numCurves = sizeof(nameTagPair)/sizeof(CurveNameTagPair);
00468        for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN)); 
00469             i++) {
00470            if (PL_strcmp(curve, nameTagPair[i].curveName) == 0)
00471                curveOidTag = nameTagPair[i].curveOidTag;
00472        }
00473     }
00474 
00475     /* Return NULL if curve name is not recognized */
00476     if ((curveOidTag == SEC_OID_UNKNOWN) || 
00477        (oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) {
00478         fprintf(stderr, "Unrecognized elliptic curve %s\n", curve);
00479        return NULL;
00480     }
00481 
00482     ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len));
00483 
00484     /* 
00485      * ecparams->data needs to contain the ASN encoding of an object ID (OID)
00486      * representing the named curve. The actual OID is in 
00487      * oidData->oid.data so we simply prepend 0x06 and OID length
00488      */
00489     ecparams->data[0] = SEC_ASN1_OBJECT_ID;
00490     ecparams->data[1] = oidData->oid.len;
00491     memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len);
00492 
00493     return ecparams;
00494 }
00495 #endif /* NSS_ENABLE_ECC */
00496 
00497 SECKEYPrivateKey *
00498 CERTUTIL_GeneratePrivateKey(KeyType keytype, PK11SlotInfo *slot, int size,
00499                          int publicExponent, const char *noise, 
00500                          SECKEYPublicKey **pubkeyp, const char *pqgFile,
00501                             secuPWData *pwdata)
00502 {
00503     CK_MECHANISM_TYPE  mechanism;
00504     SECOidTag          algtag;
00505     PK11RSAGenParams   rsaparams;
00506     SECKEYPQGParams  * dsaparams = NULL;
00507     void             * params;
00508     SECKEYPrivateKey * privKey = NULL;
00509 
00510     if (slot == NULL)
00511        return NULL;
00512 
00513     if (PK11_Authenticate(slot, PR_TRUE, pwdata) != SECSuccess)
00514        return NULL;
00515 
00516     /*
00517      * Do some random-number initialization.
00518      */
00519 
00520     if (noise) {
00521        SECStatus rv = CERTUTIL_FileForRNG(noise);
00522        if (rv != SECSuccess) {
00523            PORT_SetError(PR_END_OF_FILE_ERROR); /* XXX */
00524            return NULL;
00525        }
00526     } else {
00527        int rv = UpdateRNG();
00528        if (rv) {
00529            PORT_SetError(PR_END_OF_FILE_ERROR);
00530            return NULL;
00531        }
00532     }
00533 
00534     switch (keytype) {
00535     case rsaKey:
00536        rsaparams.keySizeInBits = size;
00537        rsaparams.pe = publicExponent;
00538        mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
00539        algtag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
00540        params = &rsaparams;
00541        break;
00542     case dsaKey:
00543        mechanism = CKM_DSA_KEY_PAIR_GEN;
00544        algtag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
00545        if (pqgFile) {
00546            dsaparams = getpqgfromfile(size, pqgFile);
00547            if (dsaparams == NULL)
00548               return NULL;
00549            params = dsaparams;
00550        } else {
00551            /* cast away const, and don't set dsaparams */
00552            params = (void *)&default_pqg_params;
00553        }
00554        break;
00555 #ifdef NSS_ENABLE_ECC
00556     case ecKey:
00557        mechanism = CKM_EC_KEY_PAIR_GEN;
00558        /* For EC keys, PQGFile determines EC parameters */
00559        if ((params = (void *) getECParams(pqgFile)) == NULL)
00560            return NULL;
00561        break;
00562 #endif /* NSS_ENABLE_ECC */
00563     default:
00564        return NULL;
00565     }
00566 
00567     fprintf(stderr, "\n\n");
00568     fprintf(stderr, "Generating key.  This may take a few moments...\n\n");
00569 
00570     privKey = PK11_GenerateKeyPair(slot, mechanism, params, pubkeyp,
00571                             PR_TRUE /*isPerm*/, PR_TRUE /*isSensitive*/, 
00572                             pwdata /*wincx*/);
00573     /* free up the params */
00574     switch (keytype) {
00575     case rsaKey: /* nothing to free */                        break;
00576     case dsaKey: if (dsaparams) CERTUTIL_DestroyParamsPQG(dsaparams); 
00577                                                              break;
00578 #ifdef NSS_ENABLE_ECC
00579     case ecKey: SECITEM_FreeItem((SECItem *)params, PR_TRUE); break;
00580 #endif
00581     }
00582     return privKey;
00583 }