Back to index

lightning-sunbird  0.9+nobinonly
mdxptest.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) 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 <stdio.h>
00038 #include <stdlib.h>
00039 #include <string.h>
00040 #include <malloc.h>
00041 #include <time.h>
00042 #include "mpi.h"
00043 #include "mpi-priv.h"
00044 
00045 /* #define OLD_WAY 1  */
00046 
00047 /* This key is the 1024-bit test key used for speed testing of RSA private 
00048 ** key ops.
00049 */
00050 
00051 #define CONST const
00052 
00053 static CONST unsigned char default_n[128] = {
00054 0xc2,0xae,0x96,0x89,0xaf,0xce,0xd0,0x7b,0x3b,0x35,0xfd,0x0f,0xb1,0xf4,0x7a,0xd1,
00055 0x3c,0x7d,0xb5,0x86,0xf2,0x68,0x36,0xc9,0x97,0xe6,0x82,0x94,0x86,0xaa,0x05,0x39,
00056 0xec,0x11,0x51,0xcc,0x5c,0xa1,0x59,0xba,0x29,0x18,0xf3,0x28,0xf1,0x9d,0xe3,0xae,
00057 0x96,0x5d,0x6d,0x87,0x73,0xf6,0xf6,0x1f,0xd0,0x2d,0xfb,0x2f,0x7a,0x13,0x7f,0xc8,
00058 0x0c,0x7a,0xe9,0x85,0xfb,0xce,0x74,0x86,0xf8,0xef,0x2f,0x85,0x37,0x73,0x0f,0x62,
00059 0x4e,0x93,0x17,0xb7,0x7e,0x84,0x9a,0x94,0x11,0x05,0xca,0x0d,0x31,0x4b,0x2a,0xc8,
00060 0xdf,0xfe,0xe9,0x0c,0x13,0xc7,0xf2,0xad,0x19,0x64,0x28,0x3c,0xb5,0x6a,0xc8,0x4b,
00061 0x79,0xea,0x7c,0xce,0x75,0x92,0x45,0x3e,0xa3,0x9d,0x64,0x6f,0x04,0x69,0x19,0x17
00062 };
00063 
00064 static CONST unsigned char default_d[128] = {
00065 0x13,0xcb,0xbc,0xf2,0xf3,0x35,0x8c,0x6d,0x7b,0x6f,0xd9,0xf3,0xa6,0x9c,0xbd,0x80,
00066 0x59,0x2e,0x4f,0x2f,0x11,0xa7,0x17,0x2b,0x18,0x8f,0x0f,0xe8,0x1a,0x69,0x5f,0x6e,
00067 0xac,0x5a,0x76,0x7e,0xd9,0x4c,0x6e,0xdb,0x47,0x22,0x8a,0x57,0x37,0x7a,0x5e,0x94,
00068 0x7a,0x25,0xb5,0xe5,0x78,0x1d,0x3c,0x99,0xaf,0x89,0x7d,0x69,0x2e,0x78,0x9d,0x1d,
00069 0x84,0xc8,0xc1,0xd7,0x1a,0xb2,0x6d,0x2d,0x8a,0xd9,0xab,0x6b,0xce,0xae,0xb0,0xa0,
00070 0x58,0x55,0xad,0x5c,0x40,0x8a,0xd6,0x96,0x08,0x8a,0xe8,0x63,0xe6,0x3d,0x6c,0x20,
00071 0x49,0xc7,0xaf,0x0f,0x25,0x73,0xd3,0x69,0x43,0x3b,0xf2,0x32,0xf8,0x3d,0x5e,0xee,
00072 0x7a,0xca,0xd6,0x94,0x55,0xe5,0xbd,0x25,0x34,0x8d,0x63,0x40,0xb5,0x8a,0xc3,0x01
00073 };
00074 
00075 
00076 #define DEFAULT_ITERS 50
00077 
00078 typedef clock_t timetype;
00079 #define gettime(x) *(x) = clock()
00080 #define subtime(a, b) a -= b
00081 #define msec(x) ((clock_t)((double)x * 1000.0 / CLOCKS_PER_SEC))
00082 #define sec(x) (x / CLOCKS_PER_SEC)
00083 
00084 struct TimingContextStr {
00085     timetype start;
00086     timetype end;
00087     timetype interval;
00088 
00089     int   minutes;  
00090     int   seconds;  
00091     int   millisecs;
00092 };
00093 
00094 typedef struct TimingContextStr TimingContext;
00095 
00096 TimingContext *CreateTimingContext(void) 
00097 {
00098     return (TimingContext *)malloc(sizeof(TimingContext));
00099 }
00100 
00101 void DestroyTimingContext(TimingContext *ctx) 
00102 {
00103     free(ctx);
00104 }
00105 
00106 void TimingBegin(TimingContext *ctx) 
00107 {
00108     gettime(&ctx->start);
00109 }
00110 
00111 static void timingUpdate(TimingContext *ctx) 
00112 {
00113 
00114     ctx->millisecs = msec(ctx->interval) % 1000;
00115     ctx->seconds   = sec(ctx->interval);
00116     ctx->minutes   = ctx->seconds / 60;
00117     ctx->seconds  %= 60;
00118 
00119 }
00120 
00121 void TimingEnd(TimingContext *ctx) 
00122 {
00123     gettime(&ctx->end);
00124     ctx->interval = ctx->end;
00125     subtime(ctx->interval, ctx->start);
00126     timingUpdate(ctx);
00127 }
00128 
00129 char *TimingGenerateString(TimingContext *ctx) 
00130 {
00131     static char sBuf[4096];
00132 
00133     sprintf(sBuf, "%d minutes, %d.%03d seconds", ctx->minutes,
00134                             ctx->seconds, ctx->millisecs);
00135     return sBuf;
00136 }
00137 
00138 static void
00139 dumpBytes( unsigned char * b, int l)
00140 {
00141     int i;
00142     if (l <= 0)
00143         return;
00144     for (i = 0; i < l; ++i) {
00145         if (i % 16 == 0)
00146             printf("\t");
00147         printf(" %02x", b[i]);
00148         if (i % 16 == 15)
00149             printf("\n");
00150     }
00151     if ((i % 16) != 0)
00152         printf("\n");
00153     printf("\n");
00154 }
00155 
00156 static mp_err
00157 testNewFuncs(const unsigned char * modulusBytes, int modulus_len)
00158 {
00159     mp_err mperr     = MP_OKAY;
00160     mp_int modulus;
00161     unsigned char buf[512];
00162 
00163     mperr = mp_init(&modulus);
00164     mperr = mp_read_unsigned_octets(&modulus,  modulusBytes,  modulus_len );
00165     mperr = mp_to_fixlen_octets(&modulus, buf, modulus_len);
00166     mperr = mp_to_fixlen_octets(&modulus, buf, modulus_len+1);
00167     mperr = mp_to_fixlen_octets(&modulus, buf, modulus_len+4);
00168     mperr = mp_to_unsigned_octets(&modulus, buf, modulus_len);
00169     mperr = mp_to_signed_octets(&modulus, buf, modulus_len + 1);
00170     mp_clear(&modulus);
00171     return mperr;
00172 }
00173 
00174 int
00175 testModExp( const unsigned char *      modulusBytes, 
00176            const unsigned int         expo,
00177            const unsigned char *      input, 
00178                  unsigned char *      output,
00179                  int                  modulus_len)
00180 {
00181     mp_err mperr     = MP_OKAY;
00182     mp_int modulus;
00183     mp_int base;
00184     mp_int exponent;
00185     mp_int result;
00186 
00187     mperr  = mp_init(&modulus);
00188     mperr += mp_init(&base);
00189     mperr += mp_init(&exponent);
00190     mperr += mp_init(&result);
00191     /* we initialize all mp_ints unconditionally, even if some fail.
00192     ** This guarantees that the DIGITS pointer is valid (even if null).
00193     ** So, mp_clear will do the right thing below. 
00194     */
00195     if (mperr == MP_OKAY) {
00196       mperr  = mp_read_unsigned_octets(&modulus,  
00197               modulusBytes + (sizeof default_n - modulus_len),  modulus_len );
00198       mperr += mp_read_unsigned_octets(&base,     input,         modulus_len );
00199       mp_set(&exponent, expo);
00200       if (mperr == MP_OKAY) {
00201 #if OLD_WAY
00202        mperr = s_mp_exptmod(&base, &exponent, &modulus, &result);
00203 #else
00204        mperr = mp_exptmod(&base, &exponent, &modulus, &result);
00205 #endif
00206        if (mperr == MP_OKAY) {
00207          mperr = mp_to_fixlen_octets(&result, output, modulus_len);
00208        }
00209       }
00210     }
00211     mp_clear(&base);
00212     mp_clear(&result);
00213 
00214     mp_clear(&modulus);
00215     mp_clear(&exponent);
00216 
00217     return (int)mperr;
00218 }
00219 
00220 int
00221 doModExp(   const unsigned char *      modulusBytes, 
00222            const unsigned char *      exponentBytes, 
00223            const unsigned char *      input, 
00224                  unsigned char *      output,
00225                  int                  modulus_len)
00226 {
00227     mp_err mperr     = MP_OKAY;
00228     mp_int modulus;
00229     mp_int base;
00230     mp_int exponent;
00231     mp_int result;
00232 
00233     mperr  = mp_init(&modulus);
00234     mperr += mp_init(&base);
00235     mperr += mp_init(&exponent);
00236     mperr += mp_init(&result);
00237     /* we initialize all mp_ints unconditionally, even if some fail.
00238     ** This guarantees that the DIGITS pointer is valid (even if null).
00239     ** So, mp_clear will do the right thing below. 
00240     */
00241     if (mperr == MP_OKAY) {
00242       mperr  = mp_read_unsigned_octets(&modulus,  
00243               modulusBytes + (sizeof default_n - modulus_len),  modulus_len );
00244       mperr += mp_read_unsigned_octets(&exponent, exponentBytes, modulus_len );
00245       mperr += mp_read_unsigned_octets(&base,     input,         modulus_len );
00246       if (mperr == MP_OKAY) {
00247 #if OLD_WAY
00248        mperr = s_mp_exptmod(&base, &exponent, &modulus, &result);
00249 #else
00250        mperr = mp_exptmod(&base, &exponent, &modulus, &result);
00251 #endif
00252        if (mperr == MP_OKAY) {
00253          mperr = mp_to_fixlen_octets(&result, output, modulus_len);
00254        }
00255       }
00256     }
00257     mp_clear(&base);
00258     mp_clear(&result);
00259 
00260     mp_clear(&modulus);
00261     mp_clear(&exponent);
00262 
00263     return (int)mperr;
00264 }
00265 
00266 int
00267 main(int argc, char **argv)
00268 {
00269     TimingContext *    timeCtx;
00270     char *             progName;
00271     long               iters       = DEFAULT_ITERS;
00272     unsigned int       modulus_len;
00273     int                       i;
00274     int                rv;
00275     unsigned char      buf [1024];
00276     unsigned char      buf2[1024];
00277 
00278     progName = strrchr(argv[0], '/');
00279     if (!progName)
00280        progName = strrchr(argv[0], '\\');
00281     progName = progName ? progName+1 : argv[0];
00282 
00283     if (argc >= 2) {
00284        iters = atol(argv[1]);
00285     }
00286 
00287     if (argc >= 3) {
00288        modulus_len = atol(argv[2]);
00289     } else 
00290        modulus_len = sizeof default_n;
00291 
00292     /* no library init function !? */
00293 
00294     memset(buf, 0x41, sizeof buf);
00295 
00296   if (iters < 2) {
00297     testNewFuncs( default_n, modulus_len);
00298     testNewFuncs( default_n+1, modulus_len - 1);
00299     testNewFuncs( default_n+2, modulus_len - 2);
00300     testNewFuncs( default_n+3, modulus_len - 3);
00301 
00302     printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
00303     rv = testModExp(default_n, 0, buf, buf2, modulus_len);
00304     dumpBytes((unsigned char *)buf2, modulus_len);
00305 
00306     printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
00307     rv = testModExp(default_n, 1, buf, buf2, modulus_len);
00308     dumpBytes((unsigned char *)buf2, modulus_len);
00309 
00310     printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
00311     rv = testModExp(default_n, 2, buf, buf2, modulus_len);
00312     dumpBytes((unsigned char *)buf2, modulus_len);
00313 
00314     printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
00315     rv = testModExp(default_n, 3, buf, buf2, modulus_len);
00316     dumpBytes((unsigned char *)buf2, modulus_len);
00317   }
00318     printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
00319     rv = doModExp(default_n, default_d, buf, buf2, modulus_len);
00320     if (rv != 0) {
00321        fprintf(stderr, "Error in modexp operation:\n");
00322        exit(1);
00323     }
00324     dumpBytes((unsigned char *)buf2, modulus_len);
00325     printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
00326 
00327     timeCtx = CreateTimingContext();
00328     TimingBegin(timeCtx);
00329     i = iters;
00330     while (i--) {
00331        rv = doModExp(default_n, default_d, buf, buf2, modulus_len);
00332        if (rv != 0) {
00333            fprintf(stderr, "Error in modexp operation\n");
00334            exit(1);
00335        }
00336     }
00337     TimingEnd(timeCtx);
00338     printf("%ld iterations in %s\n", iters, TimingGenerateString(timeCtx));
00339     printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
00340 
00341     return 0;
00342 }