Back to index

lightning-sunbird  0.9+nobinonly
makepqg.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  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 #include "prtypes.h"
00038 #include "prtime.h"
00039 #include "prlong.h"
00040 
00041 #include "nss.h"
00042 #include "secutil.h"
00043 #include "secitem.h"
00044 #include "pk11func.h"
00045 #include "pk11pqg.h"
00046 
00047 #if defined(XP_UNIX)
00048 #include <unistd.h>
00049 #endif
00050 
00051 #include "plgetopt.h"
00052 
00053 #define BPB 8 /* bits per byte. */
00054 
00055 char  *progName;
00056 
00057 
00058 const SEC_ASN1Template seckey_PQGParamsTemplate[] = {
00059     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPQGParams) },
00060     { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,prime) },
00061     { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,subPrime) },
00062     { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,base) },
00063     { 0, }
00064 };
00065 
00066 
00067 
00068 void
00069 Usage(void)
00070 {
00071     fprintf(stderr, "Usage:  %s\n", progName);
00072     fprintf(stderr, 
00073 "-a   Output DER-encoded PQG params, BTOA encoded.\n"
00074 "     -l prime-length       Length of prime in bits (1024 is default)\n"
00075 "     -o file               Output to this file (default is stdout)\n"
00076 "-b   Output DER-encoded PQG params in binary\n"
00077 "     -l prime-length       Length of prime in bits (1024 is default)\n"
00078 "     -o file               Output to this file (default is stdout)\n"
00079 "-r   Output P, Q and G in ASCII hexadecimal. \n"
00080 "     -l prime-length       Length of prime in bits (1024 is default)\n"
00081 "     -o file               Output to this file (default is stdout)\n"   
00082 "-g bits       Generate SEED this many bits long.\n"
00083 );
00084     exit(-1);
00085 
00086 }
00087 
00088 SECStatus
00089 outputPQGParams(PQGParams * pqgParams, PRBool output_binary, PRBool output_raw,
00090                 FILE * outFile)
00091 {
00092     PRArenaPool   * arena          = NULL;
00093     char          * PQG;
00094     SECItem       * pItem;
00095     int             cc;
00096     SECStatus       rv;
00097     SECItem         encodedParams;
00098 
00099     if (output_raw) {
00100        SECItem item;
00101 
00102        rv = PK11_PQG_GetPrimeFromParams(pqgParams, &item);
00103        if (rv) {
00104            SECU_PrintError(progName, "PK11_PQG_GetPrimeFromParams");
00105            return rv;
00106        }
00107        SECU_PrintInteger(outFile, &item,    "Prime",    1);
00108        SECITEM_FreeItem(&item, PR_FALSE);
00109 
00110        rv = PK11_PQG_GetSubPrimeFromParams(pqgParams, &item);
00111        if (rv) {
00112            SECU_PrintError(progName, "PK11_PQG_GetPrimeFromParams");
00113            return rv;
00114        }
00115        SECU_PrintInteger(outFile, &item, "Subprime", 1);
00116        SECITEM_FreeItem(&item, PR_FALSE);
00117 
00118        rv = PK11_PQG_GetBaseFromParams(pqgParams, &item);
00119        if (rv) {
00120            SECU_PrintError(progName, "PK11_PQG_GetPrimeFromParams");
00121            return rv;
00122        }
00123        SECU_PrintInteger(outFile, &item,     "Base",     1);
00124        SECITEM_FreeItem(&item, PR_FALSE);
00125 
00126        fprintf(outFile, "\n");
00127        return SECSuccess;
00128     }
00129 
00130     encodedParams.data = NULL;
00131     encodedParams.len  = 0;
00132     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
00133     if (!arena) {
00134        SECU_PrintError(progName, "PORT_NewArena");
00135        return SECFailure;
00136     }
00137     pItem = SEC_ASN1EncodeItem(arena, &encodedParams, pqgParams,
00138                             seckey_PQGParamsTemplate);
00139     if (!pItem) {
00140        SECU_PrintError(progName, "SEC_ASN1EncodeItem");
00141        PORT_FreeArena(arena, PR_FALSE);
00142        return SECFailure;
00143     }
00144     if (output_binary) {
00145        size_t len;
00146        len = fwrite(encodedParams.data, 1, encodedParams.len, outFile);
00147        PORT_FreeArena(arena, PR_FALSE);
00148        if (len != encodedParams.len) {
00149             fprintf(stderr, "%s: fwrite failed\n", progName);
00150             return SECFailure;
00151        }
00152        return SECSuccess;
00153     }
00154 
00155     /* must be output ASCII */
00156     PQG = BTOA_DataToAscii(encodedParams.data, encodedParams.len);    
00157     PORT_FreeArena(arena, PR_FALSE);
00158     if (!PQG) {
00159        SECU_PrintError(progName, "BTOA_DataToAscii");
00160        return SECFailure;
00161     }
00162 
00163     cc = fprintf(outFile,"%s\n",PQG);
00164     PORT_Free(PQG);
00165     if (cc <= 0) {
00166         fprintf(stderr, "%s: fprintf failed\n", progName);
00167         return SECFailure;
00168     }
00169     return SECSuccess;
00170 }
00171 
00172 SECStatus
00173 outputPQGVerify(PQGVerify * pqgVerify, PRBool output_binary, PRBool output_raw,
00174                 FILE * outFile)
00175 {
00176     SECStatus rv = SECSuccess;
00177     if (output_raw) {
00178        SECItem item;
00179        unsigned int counter;
00180 
00181        rv = PK11_PQG_GetHFromVerify(pqgVerify, &item);
00182        if (rv) {
00183            SECU_PrintError(progName, "PK11_PQG_GetHFromVerify");
00184            return rv;
00185        }
00186        SECU_PrintInteger(outFile, &item,        "h",        1);
00187        SECITEM_FreeItem(&item, PR_FALSE);
00188 
00189        rv = PK11_PQG_GetSeedFromVerify(pqgVerify, &item);
00190        if (rv) {
00191            SECU_PrintError(progName, "PK11_PQG_GetSeedFromVerify");
00192            return rv;
00193        }
00194        SECU_PrintInteger(outFile, &item,     "SEED",     1);
00195        fprintf(outFile, "    g:       %d\n", item.len * BPB);
00196        SECITEM_FreeItem(&item, PR_FALSE);
00197 
00198        counter = PK11_PQG_GetCounterFromVerify(pqgVerify);
00199        fprintf(outFile, "    counter: %d\n", counter);
00200        fprintf(outFile, "\n");
00201     }
00202     return rv;
00203 }
00204 
00205 int
00206 main(int argc, char **argv)
00207 {
00208     FILE          * outFile               = NULL;
00209     char          * outFileName         = NULL;
00210     PQGParams     * pqgParams             = NULL;
00211     PQGVerify     * pqgVerify           = NULL;
00212     int             keySizeInBits  = 1024;
00213     int             j;
00214     int             g                   = 0;
00215     SECStatus       rv                    = 0;
00216     SECStatus       passed         = 0;
00217     PRBool          output_ascii   = PR_FALSE;
00218     PRBool          output_binary  = PR_FALSE;
00219     PRBool          output_raw            = PR_FALSE;
00220     PLOptState *optstate;
00221     PLOptStatus status;
00222 
00223 
00224     progName = strrchr(argv[0], '/');
00225     if (!progName)
00226        progName = strrchr(argv[0], '\\');
00227     progName = progName ? progName+1 : argv[0];
00228 
00229     /* Parse command line arguments */
00230     optstate = PL_CreateOptState(argc, argv, "?abg:l:o:r" );
00231     while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
00232        switch (optstate->option) {
00233 
00234          case 'l':
00235            keySizeInBits = atoi(optstate->value);
00236            break;
00237 
00238          case 'a':
00239            output_ascii = PR_TRUE;  
00240            break;
00241 
00242          case 'b':
00243            output_binary = PR_TRUE;
00244            break;
00245 
00246          case 'r':
00247            output_raw = PR_TRUE;
00248            break;
00249 
00250          case 'o':
00251            if (outFileName) {
00252               PORT_Free(outFileName);
00253            }
00254            outFileName = PORT_Strdup(optstate->value);
00255            if (!outFileName) {
00256               rv = -1;
00257            }
00258            break;
00259 
00260          case 'g':
00261            g = atoi(optstate->value);
00262            break;
00263 
00264          default:
00265          case '?':
00266            Usage();
00267            break;
00268 
00269        }
00270     }
00271     PL_DestroyOptState(optstate);
00272 
00273     if (status == PL_OPT_BAD) {
00274         Usage();
00275     }
00276 
00277     /* exactly 1 of these options must be set. */
00278     if (1 != ((output_ascii  != PR_FALSE) + 
00279              (output_binary != PR_FALSE) +
00280              (output_raw    != PR_FALSE))) {
00281        Usage();
00282     }
00283 
00284     j = PQG_PBITS_TO_INDEX(keySizeInBits);
00285     if (j < 0) {
00286        fprintf(stderr, "%s: Illegal prime length, \n"
00287                      "\tacceptable values are between 512 and 1024,\n"
00288                      "\tand divisible by 64\n", progName);
00289        return 2;
00290     }
00291     if (g != 0 && (g < 160 || g >= 2048 || g % 8 != 0)) {
00292        fprintf(stderr, "%s: Illegal g bits, \n"
00293                      "\tacceptable values are between 160 and 2040,\n"
00294                      "\tand divisible by 8\n", progName);
00295        return 3;
00296     }
00297 
00298     if (!rv && outFileName) {
00299        outFile = fopen(outFileName, output_binary ? "wb" : "w");
00300        if (!outFile) {
00301            fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
00302                   progName, outFileName);
00303            rv = -1;
00304        }
00305     }
00306     if (outFileName) {
00307        PORT_Free(outFileName);
00308     }
00309     if (rv != 0) {
00310        return 1;
00311     }
00312 
00313     if (outFile == NULL) {
00314        outFile = stdout;
00315     }
00316 
00317 
00318     NSS_NoDB_Init(NULL);
00319 
00320     if (g) 
00321        rv = PK11_PQG_ParamGenSeedLen((unsigned)j, (unsigned)(g/8), 
00322                                 &pqgParams, &pqgVerify);
00323     else 
00324        rv = PK11_PQG_ParamGen((unsigned)j, &pqgParams, &pqgVerify);
00325     /* below here, must go to loser */
00326 
00327     if (rv != SECSuccess || pqgParams == NULL || pqgVerify == NULL) {
00328        SECU_PrintError(progName, "PQG parameter generation failed.\n");
00329        goto loser;
00330     } 
00331     fprintf(stderr, "%s: PQG parameter generation completed.\n", progName);
00332 
00333     rv = outputPQGParams(pqgParams, output_binary, output_raw, outFile);
00334     if (rv) {
00335        fprintf(stderr, "%s: failed to output PQG params.\n", progName);
00336        goto loser;
00337     }
00338     rv = outputPQGVerify(pqgVerify, output_binary, output_raw, outFile);
00339     if (rv) {
00340        fprintf(stderr, "%s: failed to output PQG Verify.\n", progName);
00341        goto loser;
00342     }
00343 
00344     rv = PK11_PQG_VerifyParams(pqgParams, pqgVerify, &passed);
00345     if (rv != SECSuccess) {
00346        fprintf(stderr, "%s: PQG parameter verification aborted.\n", progName);
00347        goto loser;
00348     }
00349     if (passed != SECSuccess) {
00350        fprintf(stderr, "%s: PQG parameters failed verification.\n", progName);
00351        goto loser;
00352     } 
00353     fprintf(stderr, "%s: PQG parameters passed verification.\n", progName);
00354 
00355     PK11_PQG_DestroyParams(pqgParams);
00356     PK11_PQG_DestroyVerify(pqgVerify);
00357     return 0;
00358 
00359 loser:
00360     PK11_PQG_DestroyParams(pqgParams);
00361     PK11_PQG_DestroyVerify(pqgVerify);
00362     return 1;
00363 }